本文共 4913 字,大约阅读时间需要 16 分钟。
在单向链表中,虽然可以轻松从头到尾遍历,但回到前一个节点却非常困难。这使得单向链表难以支持复杂的操作,如插入删除等。
双向链表通过引入前驱和后驱指针,既可以从头到尾遍历,也能从尾到头遍历。这种双向连接方式有效解决了单向链表的局限性。
双向链表的每个节点包含三个部分:前驱指针(prev)、节点数据(item)和后驱指针(next)。链表的首节点的前驱指针为null,末节点的后驱指针为null。
function DoublyLinkedList() { // 内部类:节点类 function Node(data) { this.data = data; this.prev = null; this.next = null; } // 属性 this.head = null; this.tail = null; this.length = 0;} DoublyLinkedList.prototype.append = function(data) { var newNode = new Node(data); if (this.length === 0) { this.head = newNode; } else { var current = this.head; while (current.next) { current = current.next; } current.next = newNode; } this.length += 1;}; // forwardString方法DoublyLinkedList.prototype.forwardString = function() { var current = this.head; var resultString = ''; while (current) { resultString += current.data + ''; current = current.prev; } return resultString;};// backwardString方法DoublyLinkedList.prototype.backwardString = function() { var current = this.head; var resultString = ''; while (current) { resultString += current.data + ''; current = current.next; } return resultString;}; DoublyLinkedList.prototype.insert = function(position, data) { // 越界判断 if (position < 0 || position > this.length) return false; var newNode = new Node(data); if (this.length === 0) { this.head = newNode; this.tail = newNode; } else { if (position === 0) { newNode.next = this.head; this.head.prev = newNode; this.head = newNode; } else if (position === this.length) { this.tail.next = newNode; newNode.prev = this.tail; this.tail = newNode; } else { var current = this.head; var index = 0; while (index++ < position) { current = current.next; } newNode.next = current; newNode.prev = current.prev; current.prev.next = newNode; current.prev = newNode; } } this.length += 1; return true;}; // 方法1(普通方法)DoublyLinkedList.prototype.get = function(position) { if (position < 0 || position >= this.length) return false; var current = this.head; var index = 0; while (index++ < position) { current = current.next; } return current.data;};// 方法2DoublyLinkedList.prototype.get = function(position) { var current = this.tail; var index = this.length - 1; while (index-- > position) { current = current.prev; } return current.data;}; DoublyLinkedList.prototype.indexOf = function(data) { var current = this.head; var index = 0; while (current) { if (current.data === data) { return index; } else { current = current.next; index++; } } return -1;}; DoublyLinkedList.prototype.update = function(position, newData) { if (position < 0 || position >= this.length) return false; var current = this.head; var index = 0; while (index++ < position) { current = current.next; } current.data = newData; return true;}; DoublyLinkedList.prototype.removeAt = function(position) { if (position < 0 || position >= this.length) return null; var current = this.head; if (this.length === 1) { this.head = null; this.tail = null; } else { if (position === 0) { this.head.next.prev = null; this.head = this.head.next; } else if (position === this.length - 1) { current = this.tail; this.tail.prev.next = null; this.tail = this.tail.prev; } else { var index = 0; while (index++ < position) { current = current.next; } current.prev.next = current.next; current.next.prev = current.prev; } } this.length -= 1; return current.data;}; DoublyLinkedList.prototype.remove = function(data) { var index = this.indexOf(data); return this.removeAt(index);}; DoublyLinkedList.prototype.isEmpty = function() { return this.length === 0;}; DoublyLinkedList.prototype.size = function() { return this.length;}; DoublyLinkedList.prototype.getHead = function() { return this.head.data;}; DoublyLinkedList.prototype.getTail = function() { return this.tail.data;}; 双向链表通过引入前驱和后驱指针,显著提升了链表的灵活性和操作能力。相比单向链表,双向链表能够支持双向遍历,但在实现和内存占用上也存在一定的挑战。
转载地址:http://ohze.baihongyu.com/