链表相对传统数组优势是:添加删除元素不会移动其它元素。链表相对传统数组缺点是:访问链表中间的元素,须要从头迭代,直到找到所需元素。上一篇文章讨论了链表,本章叙述双向链表。双向链表是双向的,一个链向上一个元素,一个链向上一个元素。 双向链表提供两种迭代方式:从头至尾和从尾到头,咱们能够访问特定一个节点的上一个元素或者下一个元素。node
简单链表和双向链表很是相似,上一章 juejin.im/post/5ccb1b… 已经介绍了基本的操做方法和写法,此次介绍双向链表和简单链表不同的一些算法。算法
function DoublyLinkedList() {
let Node = function(element) {
this.element = element;
this.next = null;
this.prev = null;
};
let length = 0,
head = null,
tail = null;
// 在任意位置插入新元素
this.insert = function(position) {
if (position >= 0 && position <= length) {
let node = new Node(element),
current = head,
previous = null,
index = 0;
if (0 === position) {
if (!head) {
head = node;
tail = node;
} else {
node.next = current;
current.prev = node;
head = node;
}
} else if (length === position) {
current = tail;
current.next = node;
node.prev = current;
tail = node;
} else {
while (index++ < position) {
previous = current;
current = current.next;
}
previous.next = node;
node.prev = previous;
current.prev = node;
node.next = current;
}
length++;
return true;
} else {
return false;
}
};
}
复制代码
插入大体分为三种场景:一、 在列表第一个位置插入元素,若是列表为空,head和tail都指向这个新节点。若是列表不为空,current将是对这个列表对一个元素的引用,node.next指向current,current.prev指向node。二、在列表最后插入一个元素,这是一种比较特殊的场景,由于最后还控制着tail指针,current指向最后一个指针的引用,而后创建里一个连接,current.next指向node,而后node.prev指向current,最后更新tail,指向node。三、在列表任意位置插入元素,首先遍历到指定位置,这里就须要在指定位置先后位新元素创建两两连接。这样才不会丢掉节点之间的关系。数组
function DoublyLinkedList() {
let Node = function(element) {
this.element = element;
this.next = null;
this.prev = null;
};
let length = 0,
head = null,
tail = null;
// 从任意位置移除元素
this.removeAt = function(position) {
if (position > -1 && position < length) {
let current = head,
previous = null,
index = 0;
if (0 === position) {
head = current.next;
if (1 === length) {
tail = null;
} else {
head.prev = null;
}
} else if (length - 1 === position) {
current = tail;
tail = current.prev;
tail.next = null;
} else {
while (index++ < position) {
previous = current;
current = current.next;
}
previous.next = current.next;
current.next.prev = previous;
}
length--;
return current.element;
} else {
return null;
}
};
}
复制代码
删除也大体分为三种场景:一、 在列表第一个位置删除元素。二、删除列表最后一个元素,这是一种比较特殊的场景,由于最后还控制着tail指针。三、在列表任意位置删除元素。bash
双向链表的删除和插入操做最基本的思想一致,在操做元素时保证元素间先后连接不能断开。post
下一章:循环链表ui