從任意位置移除元素
從雙向鏈表中移除元素跟鏈表非常類似。唯一的區別就是還需要設置前一個位置的指針。我們來看一下它的實現:
this.removeAt = function(position){
//檢查越界值
if(position > -1 && position < length) {
var current = head,
previous,
index = 0;
//移除第一項
if(position === 0){
head = current.next;// {1}
//如果只有一項,更新tail //新增的
if(length === 1) {// {2}
tail = null;
} else {
head.prev = null;// {3}
}
} else if( position === length - 1){//最後一項 //新增的
current = tail;// {4}
tail = current.prev;
tail.next = null;
} else{
while(index++ < position){// {5}
previous = current;
current = current.next;
}
//將previous與current的下一項鍊接起來——跳過current
previous.next = current.next;// {6}
current.next.prev = previous;//新增的
}
length--;
return current.element;
} else {
return null;
}
}
我們需要處理三種場景:從頭部、從中間和從尾部移除一個元素。
我們來看看如何移除第一個元素。
- current變量是對列表中第一個元素的引用,也就是我們想移除的元素。
- 需要做的就是改變head 的引用, 將其從current 改爲下一個元素(current.next——行{1})。
- 但我們還需要更新current.next指向上一個元素的指針(因爲第一個元素的prev指針是null)。
- 因此,把head.prev的引用改爲null(行{3}——因爲head也指向列表中新的第一個元素,或者也可以用current.next.prev)。
- 由於還需要控制tail的引用,我們可以檢查要移除的元素是否是第一個元素,如果是,只需要把tail也設爲null(行{2})。
下圖勾畫了從雙向鏈表移除第一個元素的過程:
下一種場景是從最後一個位置移除元素。
- 既然已經有了對最後一個元素的引用(tail),我們就不需要爲找到它而迭代列表。
- 這樣我們也就可以把tail的引用賦給current變量(行{4})。
- 接下來,需要把tail的引用更新爲列表中倒數第二個元素(current.prev,或者tail.prev也可以)。
- 既然tail指向了倒數第二個元素,我們就只需要把next指針更新爲null(tail.next= null)。
下圖演示了這一行爲:
第三種也是最後一種場景:從列表中間移除一個元素。
- 首先需要迭代列表,直到到達要找的位置(行{5})。
- current變量所引用的就是要移除的元素。
- 那麼要移除它,我們可以通過更新previous.next和current.next.prev的引用,在列表中跳過它。
- 因此,previous.next將指向current.next,而current.next.prev將指向previous.
如下圖所示: