js實現資料結構—連結串列
阿新 • • 發佈:2018-12-16
一、單鏈表建構函式
function LinkedList() { /** * 資料節點建構函式 * * @param {*} data */ function Node(data) { this.data = data; this.next = null; } let length = 0; let head = null; let tail = null; /** * 連結串列尾部追加資料 * * @param {*} item */ this.append = function (item) { const newNode = new Node(item); if (0 < length) { tail.next = newNode; tail = newNode; } else { head = tail = newNode; } length++; }; /** * 在指定索引位置的前面插入資料 * * @param {number} index 指定的索引位置 * @param {*} item * @returns {boolean} 返回是否成功 */ this.insert = function (index, item) { if (0 <= index && index <= length) { const newNode = new Node(item); if (0 < index && index < length) { // 在中間新增 let prevNode = null; let targetNode = head; let prevIndex = 0; while ((prevIndex++) < index) { prevNode = targetNode; targetNode = targetNode.next; } prevNode.next = newNode; newNode.next = targetNode; } else if (0 === index) { // 在頭部新增 newNode.next = head; head = newNode; } else { // 在尾部新增 this.append(item); } length++; return true; } else { return false; } }; /** * 刪除指定索引位置處的資料項。發生錯誤將throw一個Error * * @param {number} index 指定的索引位置 * @returns {*} 返回被刪除的資料 */ this.remove = function (index) { if (0 <= index && index < length) { let targetNode; if (0 < index) { // 刪除非頭部 let prevNode = null; targetNode = head; let prevIndex = 0; while ((prevIndex++) < index) { prevNode = targetNode; targetNode = targetNode.next; } prevNode.next = targetNode.next; targetNode.next = null; // 如果刪除的是最後一個,把tail指向倒數第二個 if ((1 + index) === length) { tail = prevNode; } } else if (0 === index) { targetNode = head; // 刪除頭部 const nextNode = targetNode.next; targetNode.next = null; head = nextNode; } length--; return targetNode.data; } else { throw new RangeError(`out of range: must between 0 and ${length}`); } }; /** * 查詢資料項在連結串列中的索引位置 * * @param {*} item * @returns {number} 索引位置,不存在則返回-1 */ this.indexOf = function (item) { let prevIndex = 0; let targetNode = head; while (!!targetNode) { if (item !== targetNode.data) { targetNode = targetNode.next; prevIndex++; } else { return prevIndex; } } return -1; }; /** * 順序打印出連結串列中的所有節點資料 * */ this.print = function () { let index = 0; let targetNode = head; while (!!targetNode) { console.log('[', index++, ']=>', targetNode.data); targetNode = targetNode.next; } }; /** * 查詢單鏈表中的第K個節點 * * @param {number} index 索引位置 * @returns {*} index位置的資料 */ this.findByIndex = function (index) { if (0 <= index && index < length) { let targetNode = head; while (0 < (index--)) { targetNode = targetNode.next; } return targetNode.data; } else { throw new RangeError(`out of range: must between 0 and ${length}`); } }; /** * 查詢單鏈表的中間位置的節點 * * @returns {*} index位置的資料 */ this.findMiddle = function () { const index = Math.round(length / 2) - 1; return this.findByIndex(index); }; }
二、實現雙向連結串列的建構函式
function DoubleLinkedList() { let length=0, head=null, tail=null; /** * 資料節點建構函式 * * @param {*} data */ function Node(data) { this.data=data; this.next=null; this.previous=null; } /** * 連結串列尾部追加資料 * * @param {*} item */ this.append = function (item) { let newNode=new Node(item); //空連結串列 if(null===head){ head=newNode; tail=head; }else{ tail.next=newNode; tail=newNode; } length++; }; /** * 在指定索引位置的前面插入資料 * * @param {number} index 指定的索引位置 * @param {*} item */ this.insert = function (index, item) { let newNode=new Node(item), current=head, previous=null, insetIndex=0; if(index < 0 || index > length){ return false }else { //在第一個位置新增 if(0 === index){ newNode.next=current; current.previous=newNode; head=newNode }else if(index === index){ //在末尾新增 current=tail; current.next=newNode; newNode.previous=current; tail=newNode; }else { while (insetIndex < index){ previous=current; current=current.next; insetIndex++; } previous.next=newNode; newNode.previous=previous; newNode.next=current; current.previous=newNode; } length++; } }; /** * 刪除指定索引位置處的資料項 * * @param {number} index 指定的索引位置 */ this.remove = function (index) { if (0 <= index && index < length) { let targetNode; if (0 < index) { // 刪除非頭部 let prevNode = null; targetNode = head; let prevIndex = 0; while ((prevIndex++) < index) { prevNode = targetNode; targetNode = targetNode.next; } prevNode.next = targetNode.next; if (!!targetNode.next) { targetNode.next.prev = prevNode; } targetNode.prev = null; targetNode.next = null; // 如果刪除的是最後一個,把tail指向倒數第二個 if ((1 + index) === length) { tail = prevNode; } } else if (0 === index) { targetNode = head; // 刪除頭部 const nextNode = targetNode.next; nextNode.prev = null; head = nextNode; targetNode.next = null; } length--; return targetNode.data; } else { throw new RangeError(`out of range: must between 0 and ${length}`); } }; /** * 順序打印出連結串列中的所有節點資料 * */ this.print = function () { console.log('順序列印'); let index = 0; let targetNode = head; while (!!targetNode) { console.log('[', index++, ']=>', targetNode.data); targetNode = targetNode.next; } }; /** * 逆序打印出連結串列中的所有節點資料 * */ this.reversePrint = function () { console.log('逆序列印'); let index = length - 1; let targetNode = tail; while (!!targetNode) { console.log('[', index--, ']=>', targetNode.data); targetNode = targetNode.prev; } }; }