鏈表是一種物理存儲單元上非連續、非順序的存儲結構,數據元素的邏輯順序是經過鏈表中的指針連接次序實現的。鏈表由一系列結點(鏈表中每個元素稱爲結點)組成,結點能夠在運行時動態生成。鏈表的節點由數據和一個或多個指針域組成。鏈表在插入和刪除操做上的算法複雜
O(1)
,而數組的插入和刪除的最大複雜度是O(n)
。可是數組在查找比鏈表更優越。node
單鏈表由一個個數據域和指針域組成的節點組成的鏈式結構,單鏈表只有指向下一個節點的指針域;而雙向鏈表由一個指向上一個節點和一個指向下一個節點的指針加數據域組成的鏈式結構。循環鏈表就是最後一個節點的指針不是指向null;而是指向head頭部虛擬節點。以下圖所示:算法
append(node)
:append是往鏈表尾部添加節點操做,其中node是須要加入鏈表的元素,返回操做成功與否布爾值。remove(index)
:delete移除第index個元素操做,返回移除的移除元素。size()
:獲取棧中的鏈表節點數量,返回一個數字。數組
isEmpty()
:判斷鏈表是否爲空,返回一個布爾值。bash
find(head,currentIndex,index)
:查找索引爲index的節點,返回該節點。數據結構
class Node {
constructor(data, next) {
this.data = data;
this.next = next;
}
}
class LinkChain {
constructor() {
this.header = new Node(null, null);
this.size = 0;
}
find(header, currentIndex, index) {
if (currentIndex === index) {
return header;
}
return this.find(header.next, ++currentIndex, index);
}
append(data, index) {
const prevNode = this.find(this.header, 0, index);
prevNode.next = new Node(data, prevNode.next);
this.size++;
return true;
}
insert(node, index) {
return this.append(data, index);
}
remove(index) {
const prevNode = this.find(this.header, 0, index);
const node = prevNode.next;
prevNode.next = node.next;
node.next = null;
this.size--;
return node;
}
length() {
return thid.size;
}
isEmpty() {
return this.size === 0;
}
toString() {
console.log(JSON.stringify(this));
}
}
const chain = new LinkChain();
chain.append('kiwis', 0);
chain.append('kiwis1', 1);
chain.append('kiwis2', 2);
chain.toString();
複製代碼
經過ES5把功能函數能夠綁定在對象的實例上,也能夠把功能函數加在函數的原型鏈上app
function Node(data,next){
this.data = data;
this.next = next;
}
function LinkChain(){
this.head = new Node(null,null);
this.length = 0;
}
LinkChain.prototype.append = function(data,index){
var prevNode = this.find(this.head,0,index);
prevNode.next = new Node(data,prevNode.next)
this.length++;
return true;
}
LinkChain.prototype.remove = function(index){
var prevNode = this.find(this.head,0,index);
var Node = prevNode.next;
prevNode.next = Node.next;
Node.next = null;
this.length--;
return Node;
}
LinkChain.prototype.size = function(){
return this.length;
}
LinkChain.prototype.isEmpty = function(){
return this.length === 0;
}
LinkChain.prototype.insert = function(node,index){
return this.append(node,index);
}
LinkChain.prototype.find = function(head,currentIndex,index){
if(currentIndex === index){
return head;
}
return this.find(head.next,++currentIndex,index);
}
複製代碼
雙向鏈表其餘操做與單鏈表操做相相似,下面ES6實現雙向鏈表的實現:函數
class Node{
constructor(data,next=null,prev=null){
this.data = data;
this.next = next;
this.prev = prev;
}
}
class LinkChain{
constructor(){
this.head = new Node(null,null,null);
this.tail = new Node(null,null,null);
this.length = 0;
}
find(head,currentIndex,index){
if(currentIndex === index){
return head;
}
return this.find(head.next,++currentIndex,index);
}
append(node,index){
const prevNode = this.find(this.head,0,index);
node.next = prevNode .next;
prevNode .next.prev = node;
prevNode.next = node;
node.prev = prevNode;
this.length++;
return true;
}
insert(node,index){
return this.append(node,index);
}
remove(index){
const prevNode = this.find(this.head,0,index);
const Node = prevNode.next;
prevNode.next = Node.next;
Node.next.prev = Node.prev;
Node.next = null;
Node.prev = null;
this.length--;
return Node;
}
size(){
return this.length;
}
isEmpty(){
return this.length === 0;
}
}
複製代碼
循環鏈表的最後一個節點再也不是指向null,而是指向虛擬的頭部head指針,其餘的操做相相似與單鏈表: ES6實現循環鏈表代碼:ui
append(node,index){
const prevNode = this.find(this.head,0,index);
const curtNode = prevNode.next;
if(!curtNode.next.data){
curtNode.next = node;
node.next = this.head;
}else{
node.next = curtNode.next;
curtNode.next = node;
}
this.length++;
return true;
}
remove(index){
const prevNode = this.find(this.head,0,index);
const curtNode = prevNode.next;
//若是隻有一個虛擬head頭部節點或刪除的是最後一個節點
if(!curtNode.next.data){
prevNode.next = this.head;
}else{
prevNode.next = curtNode.next;
curtNode.next = null;
}
this.length --;
return true;
}
複製代碼
完成鏈表數據結構編碼this