队列
队列是一种先进先出 的数据结构,类似于排队点餐,排在第一个的就可以第一个点餐,而后面的只能按照队列顺序等待执行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| function Queue() { let items = []; this.enqueue = function(element) { items.push(element); }; this.dequeue = function() { return items.shift(); }; this.front = function() { return items[0]; };
this.clear = function() { items = []; };
this.isEmpty = function() { return items.length == 0; };
this.size = function() { return items.length; }; this.print = function() { console.log(items); }; } var queue = new Queue(); queue.enqueue(2); queue.print(); queue.size();
|
简单的实现了一个列队构造函数
简单的运用一下
优先队列
队列的添加和移除都是基于优先级,实现一个优先队列,有两种选项,设置优先级,然后再正确的位置添加元素,或者用入队操作添加元素,然后按照优先级移除。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| function PriorityQueue() { const items = []; function QueueElement(element, priority) { this.element = element; this.priority = priority; } this.enqueue = function(element, priority) { const queueElement = new QueueElement(element, priority); if (items.length === 0) { items.push(queueElement); } else { let added = false; for (var i = 0; i < items.length; i++) { if (queueElement.priority < items[i].priority) { items.splice(i, 0, queueElement); added = true; break; } } } if (!added) { items.push(queueElement); } }; this.dequeue = function() { return items.shift(); }; this.front = function() { return items[0]; }; this.isEmpty = function() { return items.length == 0; }; this.size = function() { return items.length; }; this.print = function() { for (var i = 0; i < items.length; i++) { console.log(items[i].element + " - " + items[i].priority); } }; }
|
循环列队
击鼓传花
击鼓传花游戏,在这个游戏中,孩子们围成一个圆圈,把花尽快的传递给旁边的人。某一时刻传花停止,这个时候花落在谁手里,谁就退出圆圈结束游戏。重复这个过程,直到只剩下一个孩子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| function hotPotato(namelist, num) { var queue = new Queue(); for (var i = 0; i < namelist.length; i++) { queue.enqueue(namelist[i]); } var eliminated = ""; while (queue.size() > 1) { for (var i = 0; i < num; i++) { queue.enqueue(queue.dequeue()); } eliminated = queue.dequeue(); console.log(eliminated + "在游戏中淘汰了。"); } return queue.dequeue(); } var names = ["a", "b", "c", "d", "e"]; var winner = hotPotato(names, 7); console.log("胜利者" + winner);
|
栈
栈,是一种先进后出的有序集合,新添加或待删除的元素都保存在栈的末位,称作栈顶,另一端成为栈底,新元素都靠近栈顶,就元素都接近栈底。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| function Stack() {
/** * 用数组来模拟栈 */ var items = [];
/** * 将元素送入栈,放置于数组的最后一位 */ this.push = function(element) { items.push(element); };
/** * 弹出栈顶元素 */ this.pop = function() { return items.pop(); };
/** * 查看栈顶元素 */ this.peek = function() { return items[items.length - 1]; }
/** * 确定栈是否为空 * @return {Boolean} 若栈为空则返回true,不为空则返回false */ this.isAmpty = function() { return items.length === 0 };
/** * 清空栈中所有内容 */ this.clear = function() { items = []; };
/** * 返回栈的长度 * @return {Number} 栈的长度 */ this.size = function() { return items.length; };
/** * 以字符串显示栈中所有内容 */ this.print = function() { console.log(items.toString()); }; }
|
十进制转任何进制代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| /** * decNumber 要转换的十进制数字 * base 目标进制基数 */ function baseConverter(decNumber, base) { var remStack = new Stack(), rem, baseString = '', digits = '0123456789ABCDEF'; white (decNumber > 0) { rem = Math.floor(decNumber % base); remStack.push(rem); decNumber = Math.floor(decNumber / base); }
white(!remStack.isEmpty()) { baseString += digits[remStack.pop()]; }
return baseString; }
|
链表
链表存储有序的元素集合,但不同于数组,链表中的元素在内存中并不是连续放置的。每个元素由一个存储元素本事的节点和一个指向下一个元素的引用组成。相对于传统的数组,链表的一个好处在于,添加或者删除元素的时候不需要移动其他元素。然而,链表需要使用指针,因此实现链表时需要额外注意。
数组和链表的一个不同在于数组可以直接访问任何位置的元素,而想要访问链表中的一个元素,需要从起点开始迭代列表。
单向链表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
| function LinkedList() { var Node = function(element) { this.element = element; this.next = null; }; var length = 0; var head = null; this.append = function(element) { var node = new Node(element), current; if (head === null) { head = node; } else { current = head; while (current.next) { current = current.next; } current.next = node; } length++; }; this.insert = function(position, element) { if (position >= 0 && position <= length) { var node = new Node(element), current = head, previous, index = 0; if (position === 0) { node.next = current; head = node; } else { while (index++ < position) { previous = current; current = current.next; } node.next = current; previous.next = node; } length++; return true; } else { return false; } }; this.removeAt = function(position) { if (position > -1 && position < length) { var current = head, previous, index = 0; if (position === 0) { head = current.next; } else { while (index++ < position) { previous = current; current = current.next; } previous.next = current.next; } length--; return current.element; } else { return null; } }; this.remove = function(element) { var index = this.indexOf(element); return this.removeAt(index); }; this.indexOf = function(element) { var current = head, index = 0; while (current) { if (element === current.element) { return index; } index++; current = current.next; } return -1; }; this.isEmpty = function() { return length === 0; }; this.size = function() { return length; }; this.getHead = function() { return head; }; this.toString = function() { var current = head, string = ""; while (current) { string += current.element; current = current.next; } return string; }; this.print = function() { console.log(this.toString()); }; }
|
双向链表
双向链表和单向链表的区别在于,在单向链表中,一个节点只有链向下一个节点的链接。而在双向链表中,链接是双向的:一个链向下一个元素,另一个链向前一个元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
| function DoublyLinkedList() { var Node = function(element) { this.element = element; this.next = null; this.prev = null; }; var length = 0; var head = null; var tail = null; this.append = function(element) { var node = new Node(element), current; if (head === null) { head = node; tail = node; } else { tail.next = node; node.prev = tail; tail = node; } length++; }; this.insert = function(position, element) { if (position >= 0 && position <= length) { var node = new Node(element), current = head, previous, index = 0; if (position === 0) { if (!head) { head = node; tail = node; } else { node.next = current; current.prev = node; head = node; } } else if (position === length) { current = tail; current.next = node; node.prev = current; tail = node; } else { while (index++ < position) { previous = current; current = current.next; } node.next = current; previous.next = node;
current.prev = node; node.prev = previous; } length++; return true; } else { return false; } }; this.removeAt = function(position) { if (position > -1 && position < length) { var current = head, previous, index = 0; if (position === 0) { head = current.next; if (length === 1) { tail = null; } else { head.prev = null; } } else if (position === length - 1) { 移除最后一项; current = tail; tail = current.prev; tail.next = null; } else { while (index++ < position) { previous = current; current = current.next; } previous.next = current.next; current.next.prev = previous; } length--; return current.element; } else { return null; } }; this.remove = function(element) { var index = this.indexOf(element); return this.removeAt(index); }; this.indexOf = function(element) { var current = head, index = -1; if (element == current.element) { return 0; } index++; while (current.next) { if (element == current.element) { return index; } current = current.next; index++; } if (element == current.element) { return index; } return -1; }; this.isEmpty = function() { return length === 0; }; this.size = function() { return length; }; this.toString = function() { var current = head, s = current ? current.element : ""; while (current && current.next) { current = current.next; s += ", " + current.element; } return s; }; this.inverseToString = function() { var current = tail, s = current ? current.element : ""; while (current && current.prev) { current = current.prev; s += ", " + current.element; } return s; }; this.print = function() { console.log(this.toString()); }; this.printInverse = function() { console.log(this.inverseToString()); }; this.getHead = function() { return head; }; this.getTail = function() { return tail; }; }
|
循环链表
循环链表可以像单向链表那样只有单向引用,也可以像双向链表那样有双向引用。循环链表和其他链表的区别在于最后一个元素指向下一个元素的引用不是 null,而是指向第一个元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
| function CircularLinkedList() { var Node = function(element){ this.element = element; this.next = null; }; var length = 0; var head = null; this.append = function(element){ var node = new Node(element), current; if (head === null){ //列表为空 head = node; } else { current = head; while(current.next !== head){ //最后一个元素将是head,而不是null current = current.next; } current.next = node; //建立连接 } node.next = head; //首尾相连起来变成一个环列表 length++; }; this.insert = function(position, element){ if (position >= 0 && position <= length){ var node = new Node(element), current = head, previous, index = 0; if (position === 0){ //在第一项 node.next = current; while(current.next !== head){ current = current.next; } head = node; current.next = head; } else { while (index++ < position){ previous = current; current = current.next; } node.next = current; previous.next = node; if (node.next === null){ //在最后一个元素更新 node.next = head; } } length++; return true; } else { return false; } }; this.removeAt = function(position){ if (position > -1 && position < length){ var current = head, previous, index = 0; if (position === 0){ while(current.next !== head){ current = current.next; } head = head.next; current.next = head; //更新最后一项 } else { while (index++ < position){ previous = current; current = current.next; } previous.next = current.next; } length--; return current.element; } else { return null; } }; this.remove = function(element){ var index = this.indexOf(element); return this.removeAt(index); }; this.indexOf = function(element){ var current = head, index = -1; if (element == current.element){ //检查第一项 return 0; } index++; while(current.next !== head){ //检查列表中间 if (element == current.element){ return index; } current = current.next; index++; } if (element == current.element){ //检查最后一项 return index; } return -1; }; this.isEmpty = function() { return length === 0; }; this.size = function() { return length; }; this.getHead = function(){ return head; }; this.toString = function(){ var current = head, s = current.element; while(current.next !== head){ current = current.next; s += ', ' + current.element; } return s.toString(); }; this.print = function(){ console.log(this.toString()); }; }
|