双链表
DoublyLinkedListNode
- doubly-linked-list/DoublyLinkedListNode.js
export default class DoublyLinkedListNode {
constructor(value, next = null, previous = null) {
this.value = value;
this.next = next;
this.previous = previous;
}
toString(callback) {
return callback ? callback(this.value) : `${this.value}`;
}
}
DoublyLinkedList
- doubly-linked-list/DoublyLinkedList.js
import DoublyLinkedListNode from './DoublyLinkedListNode.js';
import Comparator from '../utils/Comparator.js';
export default class DoublyLinkedList {
constructor(comparatorFunction) {
/** @var LinkedListNode */
this.head = null;
/** @var LinkedListNode */
this.tail = null;
this.compare = new Comparator(comparatorFunction);
}
append(value) {
const newNode = new DoublyLinkedListNode(value);
if (!this.head) {
this.head = newNode;
this.tail = newNode;
return this;
}
newNode.previous = this.tail;
this.tail.next = newNode;
this.tail = newNode;
return this;
}
prepend(value) {
const newNode = new DoublyLinkedList(value);
newNode.next = this.head;
if (this.head) {
this.head.previous = newNode;
}
this.head = newNode;
// If there is no tail yet let's make new node a tail.
if (!this.tail) {
this.tail = newNode;
}
return this;
}
delete(value) {
if (!this.head) {
return null;
}
let deletedNode = null;
let currentNode = this.head;
while (currentNode) {
if (this.compare.equal(currentNode.value, value)) {
deletedNode = currentNode;
if (deletedNode === this.head) {
this.head = deletedNode.next;
if (this.head) {
this.head.previous = null;
}
if (deletedNode === this.tail) {
this.tail = null;
}
} else if (deletedNode === this.tail) {
this.tail = deletedNode.previous;
this.tail.next = null;
} else {
deletedNode.previous.next = deletedNode.next;
deletedNode.next.previous = deletedNode.previous;;
}
}
currentNode = currentNode.next;
}
return deletedNode;
}
find({ value = undefined, callback = undefined }) {
if (!this.head) {
return null;
}
let currentNode = this.head;
while(currentNode) {
if (callback && callback(currentNode.value)) {
return currentNode;
}
if (value !== undefined && this.compare.equal(currentNode.value, value)) {
return currentNode;
}
currentNode = currentNode.next;
}
return null;
}
reverse() {
let current = this.head;
let prev = null;
let next = null;
while (current) {
// Store next node.
next = current.next;
prev = current.previous;
// Change next node of the current node so it would link to previous node.
current.next = prev;
current.previous = next;
// Move prevNode and currNode nodes one step forward.
prev = current;
current = next;
}
this.tail = this.head;
this.head = prev;
return this;
}
fromArray(values) {
values.forEach((value) => this.append(value));
return this;
}
toArray() {
const nodes = [];
let currentNode = this.head;
while (currentNode) {
nodes.push(currentNode);
currentNode = currentNode.next;
}
return nodes;
}
toString() {
return this.toArray().map(node => node.toString());
}
}