class Node {
/**
* Creates a Node with two pointers (next and prev) and data.
* @param {*} data anything
*/
constructor(data = null) {
this.data = data
this.next = null
this.prev = null
}
/**
* inserts after the Node
* @param {Node} node
*/
insertAfter(node) {
let next = node.next
this.next = next
this.prev = node
node.next = this
}
/**
*
* @param {Node} node
*/
insertBefore(node) {
let prev = node.prev
this.next = node
this.prev = prev
node.prev = this
}
}
class List {
/**
* Creates an empty List
*/
constructor() {
this.head = null
this.tail = null
}
/**
* Pushes a Node to the List
* @param {Node} node
*/
push(node) {
if (this.head === null) {
this.head =
this.tail = node
} else {
let t = this.tail
t.next = node
node.prev = t
this.tail = node
}
}
/**
* Pops a Node from the List
* @returns {Node} the popped element
*/
pop() {
let t = this.tail
this.tail = this.tail.prev
if (this.tail === null) {
this.head = this.tail
}
return t
}
/**
* Calls iteratee on each Node of the List. Alters the Node.
* @param {Iteratee} iteratee
*/
map(iteratee) {
let p = this.head
while (p) {
iteratee(p)
p = p.next
}
}
/**
* Implements a soft swap of two elements. Actual objects are the same just
* their 'data' property is swapped.
* @param {Node} left
* @param {Node} right
*/
swap(left, right) {
[left.data, right.data] = [right.data, left.data]
}
/**
* removes a Node from the List
* @param {Node} node
*/
remove(node) {
let prev = node.prev
let next = node.next
prev.next = next
next.prev = prev
return node
}
/**
* Returns all list nodes' data concatenated into a single string
* @returns {String}
*/
toString() {
let items = []
this.map((node) => items.push(JSON.stringify(node.data)))
return items.join(' ')
}
}
module.exports = {Node, List}