链表存储有序的指向元素集合,但不同于数组,链表中的元素在内存中并不是连续放置的。每个元素有一个存储元素本身节点和一个 指向下一元素的引用组成。
1.创建一个链表
首先初始化链表LinkedList类
function LinkedList(){ var Node = function element(){ this.element = element; this.next = null } var length = 0; var head = null; this.append = function(element){}; this.insert = function(position,element){}; this.removeAt = function(positon){}; this.remove = function(element){}; this.indexOf = function(element){}; this.isEmpty = function(){}; this.size = function(){}; this.getHead = function(){}; this.toString = function(){}; this.print = function(){}; }
1.1 向链表尾部追加元素
有两种情况,一种链表为空,添加的是第一个元素,另一种是链表不为空,向其追加元素
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++ };
1.2 从链表中移除元素
移除也有两种场景,第一种是移除第一个元素,第二种是移除第一个以外的任意元素; 实现两种移除方法:第一种是从特定位置移除一个元素,第二种是根据元素的值移除元素
首先实现从给定位置移除一个元素的方法
this.removeAt = function(positon){ // 检查越界值 if (positon>-1&&positon<length) { var current = head, previous, index=0; // 移除第一项 if (positon===0) { head = current.next; } else{ while(index++<positon){ previous = current; current = current.next; } // 将previous与current的下一项链接起来,跳过current,从而删除current previous.next = current.next; } length--; // 返回被删除的元素 return current.element } else{ return null; } };
1.3 在任意位置插入一个元素
以下是insert方法的实现买这个方法可以再任意位置插入一个元素
this.insert = function(position,element){ // 检查越界值 if (positon>-1&&positon<length) { var node = new Node(element), current = head, privious, index = 0; // 在第一个位置插入 if (positon===0) { node.next = current; head = node; } else{ while(index++<positon){ previous = current; current = current.next; } node.next = current; previous.next = node; } length++; return true; } else{ return false; } };
1.4 其它方法的实现
1.toString方法
this.toString = function(){ var current = head, string = ''; while(current){ string += ","+current.element; current = current.next; } return string.slice(1); };
2.indexOf方法
this.indexOf = function(element){ var current = head, index = 0; while(current){ if(element===current.element){ return index; } index++; current = current.next; } return -1; };
实现了这个方法之后,就可以实现上文中提到的移除指定元素的方法remove
this.remove = function(element){ var index = this.indexOf(element); return this.removeAt(index); };
2.isEmpty,size,getHead方法
this.isEmpty = function(){ return length = 0; }; this.size = function(){ return length; }; this.getHead = function(){ return head; };
isEmpty方法判断链表是否为空,size方法返回链表的长度,getHead返回链表的一个节点
2.双向链表
双向链表中:一个链向下一个元素,另一个链向前一个元素
function DoubleLinkedList(){ var Node = function(element){ this.element = element; this.next = null; this.prev = null; }; var length = 0; var head = null; var tail = null; }
双向链表提供了两种迭代链表的方法,从头到尾或者从尾到头。
2.1 在任意位置插入一个元素
this.insert = function(positon,element){ // 检查越界值 if (positon>-1&&positon<length) { var node = new Node(element), current = head, previous, index = 0; // 在第一个位置插入 if (positon===0) { if (!head) { head = node; tail = node; } else{ node.next = current; current.prev = node; head = node; } } else if (positon === length) { current = tail; current.next = node; node.prev = current; tail = node; } else{ while(index++<positon){ previous = current; current = current.next; } node.next = current; previous.next = node; current.previous = node; node.prev = previous; } length++; return true; } else{ return false; } }
2.2 从任意位置移除元素
this.removeAt = function(){ // 检查越界值 if (positon>-1&&positon<length){ var current = head, previous, index = 0; // 移除第一项 if (positon === 0) { head = current.next; // 如果只有一项,更新tail if (length === 1) { tail = null; } else{ head.prev = null; } } else if(positon === length-1){ current = tail; tail = current.prev; tail.next = null; } else{ while(index++<positon){ previous = current; current = current.next; } // 将previous和current的下一项链接起来 previous.next = current.next; current.next.prev = previous; } length--; return current.element; } else{ return null; } }
3.循环链表
循环链表和链表唯一区别就是,最后一个元素指向下一个元素的指针不是引用null,而是指向第一个元素。