1.数组的缺点
在很多编程语言中,数组的长度是固定的,在数组中,添加和删除元素也很麻烦。
JavaScript中数组的主要问题是,他们被实现成了对象,与其它语言的数组相比,效率很低。
如果发现数组在实际使用时很慢,就可以使用链表来代替。如果需要随机访问,数组仍然是更好的选择。
2.定义链表
链表是由一组节点组成的集合。每个节点都使用一个对象的引用指向它的后继。指向另一个结点的引用叫做链。
数组元素靠他们的位置进行引用,链表元素则是靠相互之间的关系进行引用。
遍历链表,就是跟着链接,从链表的首元素一直走到尾元素(但这不包含链表的头节点,头节点常常用来作为链表的接入点),链表的伪元素指向一个null节点。
-
向链表中插入一个节点
修改前驱,使其指向新加入的节点,而新加入的节点则指向原来前驱指向的节点。
-
从链表中删除一个元素
将待删除元素的前驱节点指向待删除元素的后继节点,同时,将待删除元素指向null,元素就删除成功了。
3.设计一个基于对象的链表
Node类 -- 表示节点
function Node(element){
this.element = element;
this.next = null;
}
LinkedList类 --对链表进行操作的方法
function LList(){
//使用一个Node对象来保存该链表的头节点
this.head = new Node("head");
this.find = find;
this.insert = insert;
this.remove = remove;
this.display = display;
}
head节点里的next属性被初始化为null,当有新元素插入时,next会指向新的元素。
插入新节点
查找
function find(item){
var currNode = this.head;
while (currNode.element != item){
currNode = currNode.next;
}
return currNode;
}
在一个已知节点后面插入元素
function insert(newElement,item){
var newNode = new Node(newElement);
var currNode = this.find(item);
newNode.next = current.next;
current.next = newNode;
}
显示链表中的元素
function display(){
var currNode = this.head;
while(!(currNode.next == null)){
//不显示头节点
print(currNode.next.element);
currNode = currNode.next;
}
}
从链表中删除一个节点
寻找待删除节点前面的节点
function findPrevious(item){
var currNode = this.head;
while(!(currNode.next == null)&&(currNode.next.element != item)){
currNode = currNode.next;
}
return currNode;
}
function remove(item){
var prevNode = this.findPrevious(item);
if(!(preNode.next == null)){
prevNode.next = prevNode.next.next;
}
}
4.双向链表
function Node (elemnet){
this.element = element;
this.next = null;
this.previous = null;
}
function insert(newElement,item){
var newNode = new Node(newElement);
var currNode = this.find(item);
newNode.next = current.next;
newNode.previous = current;
current.next = newNode;
}
function remove(item){
var currNode = this.find(item);
if(!(currNode.next == null)){
currNode.previous.next =currNode.next;
currNode.next.previous = currNode.previous;
currNode.next = null;
currNode.previous = null;
}
}
//查找最后的节点
function findLast(){
var currNode = this.head;
while(!(currNode.next == null)){
currNode = currNode.next;
}
return currNode;
}
//反序显示双向链表中的元素
function dispReverse(){
var currNode = this.head;
currNode = this.findLast();
while(!(currNode.previous == null)){
print(currNode.element);
currNode = currNode.previous;
}
}
5.循环列表
循环链表和单项链表类似,节点类型都是一样的。唯一的区别是,在创建循环链表时,让其头节点的next属性指向它本身。
head.next = head;
function LList(){
//使用一个Node对象来保存该链表的头节点
this.head = new Node("head");
this.head.next = this.head;
this.find = find;
this.insert = insert;
this.remove = remove;
this.display = display;
this.findPrevious = findPrevious;
}
function display(){
var currNode = this.head;
while(!(currNode.next == null)&&!(currNode.next.element == "head")){
//不显示头节点
print(currNode.next.element);
currNode = currNode.next;
}
}