- 单向链表的缺点:只能单向遍历,根据当前节点能找到下一个节点,但是很难找到上一个节点
- 双向链表:参考文章
有头节点head和尾节点tail
function DoubleLinkedList() {
this.length = 0;//链表长度
this.headerNode = null;//头节点
this.tailNode = null;//尾节点
function NewNode(data) {
this.data = data;
this.prevNode = null;
this.nextNode = null
}
/*
向链表的尾部添加节点 两种情况
1.链表为空
2.链表不为空
*/
DoubleLinkedList.prototype.appendNode = function (data) {
//创建节点
let newNode = new NewNode(data);
let index = 0;
let currentNode = this.headerNode;
if (this.length == 0) {
this.headerNode = newNode; //如果链表为空 要添加的节点既是头节点又是尾节点
this.tailNode = newNode;
} else {
//如果链表不为空 链表的尾节点的next指向要添加的节点
//要添加的节点设置为新的尾节点
//原来的尾节点设置为新的尾节点prev
this.tailNode.nextNode = newNode;
newNode.prevNode = this.tailNode;
this.tailNode = newNode;
}
this.length++;
}
/*
将链表元素转换为字符串 前向遍历和后向遍历
*/
DoubleLinkedList.prototype.forwardString = function () {
let resultString = '';
let currentNode = this.headerNode;
while (currentNode) {
resultString += currentNode.data + '';
currentNode = currentNode.nextNode;
}
return resultString;
}
DoubleLinkedList.prototype.reverseString = function () {
let resultString = '';
let currentNode = this.tailNode;
while (currentNode) {
resultString += currentNode.data + '';
currentNode = currentNode.prevNode;
}
return resultString;
}
/*
* 向链表的任意位置插入元素
*/
DoubleLinkedList.prototype.insertNode = function (position, data) {
//创建节点
let newNode = new NewNode(data);
//位置越界判断
if (position < 0 || position > this.length) return -1;
if (this.length == 0) { //如果链表为空
this.headerNode = newNode;
this.tailNode = newNode;
} else {
//如果链表不为空
if (position == 0) {
//链表不为空,向头部添加节点
this.headerNode.prevNode = newNode;//将新节点设置为原来的头节点的prev
newNode.nextNode = this.headerNode;//原来的头节点设置为新的节点的next
this.headerNode = newNode;//新节点设置为新的头节点
} else if (position == this.length) {
//链表不为空,向尾部添加节点
newNode.prevNode = this.tailNode;//原来的尾节点设置为新的尾节点的prev
this.tailNode.nextNode = newNode;//将新节点设置为原来的尾节点的next
this.tailNode = newNode;//将新节点设置为新的尾节点
} else {
//向中间添加节点
let index = 0;
let currentNode = this.headerNode;
let previousNode = null;
while (index < position) {
previousNode = currentNode; //保存前一个节点
currentNode = currentNode.nextNode;
index++;
}
newNode.prevNode = previousNode;
newNode.nextNode = currentNode;
previousNode.nextNode = newNode;
currentNode.prevNode = newNode;
}
}
this.length++;
}
/*
在链表中任意位置删除节点
*/
DoubleLinkedList.prototype.removeNode = function (position) {
//位置越界判断
if(position <0 || position > this.length-1) return -1;
if(this.length ==1){
//如果链表的长度为1
this.headerNode = null;
this.tailNode = null;
}else{
//在链表长度大于1时删除头节点
if(position == 0){
this.headerNode.nextNode.prevNode = null;
this.headerNode = this.headerNode.nextNode;
}else if(position == this.length - 1){
this.tailNode.prevNode.nextNode = null;
this.tailNode = this.tailNode.prevNode;
}else{
let index = 0;
let currentNode = this.headerNode;
while(index < position){
currentNode = currentNode.nextNode;
index++;
}
currentNode.prevNode.nextNode = currentNode.nextNode;
currentNode.nextNode.prevNode = currentNode.prevNode;
}
}
this.length --;
}
}
let dl = new DoubleLinkedList();
dl.appendNode('aaa');
dl.appendNode('bbb');
dl.appendNode('ccc');
dl.appendNode('dd');
dl.removeNode(2);
console.log(dl)