双向链表在任意位置插入一个新元素
//在任意位置插入一个新元素
this.insert = function(position,element){
//检查越界值
if(position >= 0 && position <= length){
var node = new Node(element),
current = head,
previous,
index = 0;
if(position === 0) {//在第一个位置添加
if(!head){//新增的 {1}
head = node;
tail = node;
} else {
node.next = current;
current.prev = node;//新增的 {2}
head = node;
}
} else if(position === length) {//最后一项 //新增的
current = tail;
current.next = node;
node.prev = current;
tail = node;
} else {
while(index++ < position){//{4}
previous = current;
current = current.next;
}
node.next = current;//{5}
previous.next = node;
current.prev = node;
node.prev = previous;
}
length++;//更新列表的长度
return true;
} else {
return false;
}
}
我们来分析第一种场景:在列表的第一个位置(列表的起点)插入一个新元素。
- 如果列表为空(行{1}),只需要把head和tail都指向这个新节点。
- 如果不为空,current变量将是对列表中第一个元素的引用。
- 就像我们在链表中所做的,把node.next设为current,而head将指向node(它将成为列表中的第一个元素)。
- 不同之处在于,我们还需要为指向上一个元素的指针设一个值。
- current.prev指针将由指向null变为指向新元素(node——行{2})。
- node.prev指针已经是null,因此不需要再更新任何东西。
下图演示了这个过程:
现在来分析一下,假如我们要在列表最后添加一个新元素。
- 这是一个特殊情况,因为我们还控制着指向最后一个元素的指针(tail)。
- current变量将引用最后一个元素(行{3})。
- 然后开始建立第一个链接:node.prev将引用current。
- current.next指针(指向null)将指向node(由于构造函数,node.next已经指向了null)。
- 然后只剩一件事了,就是更新tail,它将由指向current变为指向node。
下图展示了这些行为:
然后还有第三种场景:在列表中间插入一个新元素。
- 就像我们在之前的方法中所做的,迭代列表,直到到达要找的位置(行{4})。
- 我们将在current和previous元素之间插入新元素。
- 首先,node.next将指向current(行{5}),而previous.next将指向node,这样就不会丢失节点之间的链接。
- 然后需要处理所有的链接:current.prev将指向node,而node.prev将指向previous。
下图展示了这一过程: