要儲存多個元素,js中數組多是最經常使用的數據結構,可是從數組的起點或中間插入或者移除項的成本很高,由於須要移動元素。
鏈表存儲有序的元素集合,但不一樣於數組,鏈表中的元素在內存中並非連續放置,而是每一個元素由一個存儲元素自己的節點和指向下一個元素的引用組成,這是正常的鏈表,雙向鏈表比正常的多了一個指向前一個的元素引用,循環鏈表能夠是單向引用,也能夠是雙向引用,循環鏈表的最後一個元素指向下一個元素的指針不是undefined而是第一個元素head.
畫的圖有點渣,這是一個雙向的循環鏈表。
建立一個最簡單的鏈表javascript
function defaultEquals(a,b){ return a===b; } class Node{ constructor(el){ this.el = el; this.next = undefined; } } class LinkedList{//單向鏈表 constructor(equals = defaultEquals){ this.count = 0; this.head = undefined; this.equalsFn = equals; } push(el){ const node = new Node(el); let current; if(!this.head){ this.head = node; }else{ current = this.head; while(current.next){ current = current.next; } current.next = node; } this.count++; } getElAt(index){//根據位置獲取元素 if(index>=0 && index<this.count){ let current = this.head; for(let i=0;i<index && current;i++){ current = current.next; } return current; } return undefined; } removeAt(index){//根據位置移除 if(index>=0 && index<this.count){ let current = this.head; if(index===0){ this.head = current.next; }else{ let previous=this.getElAt(index-1);//獲取前一個 current = previous.next; previous.next = current.next; } this.count--; return current.el; } return undefined; } insert(el,index){//任意位置插入 if(index>=0 && index<=this.count){ const node = new Node(el); if(index===0){ const current = this.head; node.next = current; this.head = node; }else{ const previous = this.getElAt(index-1); const current = previous.next; node.next = current; previous.next = node; } this.count++; return true; } return false; } indexOf(el){ let current = this.head; for(let i=0;i<this.count;i++){ if(this.equalsFn(current.el,el)){ return i; } current = current.next; } return -1; } remove(el){ let index = this.indexOf(el); return this.removeAt(index); } size(){ return this.count; } isEmpty(){ return this.size() === 0; } getHead(){ return this.head; } toString(){ if(!this.head){ return ''; } let str = `${this.head.el}`; let current = this.head.next; for(let i=0;i<this.size() && current;i++){ str=`${str}${current.el}`; current = current.next; } return str; } }
雙向鏈表,增長一個指向前一個元素的引用java
class DoublyNode extends Node{ constructor(el,next,prev){ super(el); this.prev = prev; } } class DoublyLinkedList extends LinkedList{ constructor(equals = defaultEquals){ super(equals); this.tail = undefined; } push(el){ const node = new DoublyNode(el); let current; if(!this.head){ this.head = node; }else{ current = this.head; while(current.next){ current = current.next; } current.next = node; node.prev = current; } this.tail = node; this.count++; } insert(el,index){ if(index>=0 && index<=this.count){ const node = new DoublyNode(el); let current = this.head; if(index===0){ if(!this.head){ this.head = node; this.tail = node; }else{ node.next = current; current.prev = node; this.head = node; } }else if(index === this.count){ current = this.tail; node.prev = current; current.next = node; this.tail = node; }else{ const previous = this.getElAt(index-1); current = previous.next; previous.next = node; node.prev = previous; node.next = current; current.prev = node; } this.count++; return true; } return false; } removeAt(index){ if(index>=0 && index<this.count){ let current = this.head; if(index===0){ this.head = current.next; if(this.count===1){ this.tail=undefined; }else{ this.head.prev = undefined; } }else if(index===this.count-1){ current = this.tail; this.tail = current.prev; this.tail.next = undefined; }else{ current = this.getElAt(index); const previous = current.prev; previous.next = current.next; current.next.prev = previous; } this.count--; return curren.el; } return undefined; } }
該內容借鑑與學習javascript數據結構與算法node