134 lines
2.9 KiB
JavaScript
134 lines
2.9 KiB
JavaScript
class DoubleLinkedListNode {
|
|
constructor(key, value) {
|
|
this.key = key;
|
|
this.value = value;
|
|
this.next = null;
|
|
this.prev = null;
|
|
};
|
|
};
|
|
|
|
class DoubleLinkedList {
|
|
constructor() {
|
|
this.map = new Map();
|
|
this.head = null;
|
|
this.tail = null;
|
|
};
|
|
|
|
getElement(id) {
|
|
const element = this.map.get(id);
|
|
if (!element) return;
|
|
|
|
return element.value;
|
|
}
|
|
|
|
hasElement(id) {
|
|
return this.map.has(id);
|
|
}
|
|
|
|
isEmpty() {
|
|
return this.head === null;
|
|
}
|
|
|
|
addFirst(key, value) {
|
|
if (this.map.has(key)) this.removeItem(key);
|
|
|
|
const newNode = new DoubleLinkedListNode(key, value);
|
|
|
|
const oldHead = this.head;
|
|
this.head = newNode;
|
|
this.head.prev = null;
|
|
|
|
if (oldHead) {
|
|
oldHead.prev = newNode;
|
|
this.head.next = oldHead;
|
|
};
|
|
|
|
this.map.set(key, {
|
|
value,
|
|
node: newNode
|
|
});
|
|
};
|
|
|
|
accumulateItem(key, value) {
|
|
if (isNaN(value)) return;
|
|
|
|
const entry = this.map.get(key);
|
|
const updatedValue = entry ? entry.value + value : value;
|
|
|
|
this.addItem(key, updatedValue);
|
|
}
|
|
|
|
addItem(key, value) {
|
|
if (this.map.has(key)) this.removeItem(key);
|
|
|
|
const temp = new DoubleLinkedListNode(key, value);
|
|
|
|
if (!this.head) {
|
|
this.head = temp;
|
|
this.tail = temp;
|
|
} else {
|
|
this.tail.next = temp;
|
|
temp.prev = this.tail;
|
|
this.tail = this.tail.next;
|
|
};
|
|
|
|
this.map.set(key, {
|
|
value,
|
|
node: temp
|
|
});
|
|
|
|
return value;
|
|
}
|
|
|
|
removeItem(key) {
|
|
const entry = this.map.get(key);
|
|
if (!entry) return;
|
|
|
|
const node = entry.node;
|
|
if (node.prev) node.prev.next = node.next;
|
|
if (node.next) node.next.prev = node.prev;
|
|
|
|
if (node === this.head) this.head = node.next;
|
|
if (node === this.tail) this.tail = node.prev;
|
|
|
|
this.map.delete(key);
|
|
|
|
return entry;
|
|
}
|
|
|
|
each(cb) {
|
|
if (this.isEmpty()) return;
|
|
if (!cb) return;
|
|
|
|
let isRunning = true;
|
|
let current = this.head;
|
|
|
|
while (current && (isRunning === undefined || isRunning)) { // I'm afraid this would backfire one day
|
|
isRunning = cb(current.key, current.value);
|
|
|
|
current = current.next;
|
|
};
|
|
|
|
return isRunning;
|
|
}
|
|
|
|
clearEach(cb) {
|
|
if (this.isEmpty()) return;
|
|
if (!cb) return;
|
|
|
|
let current = this.head;
|
|
while (current) {
|
|
cb(current.key, current.value);
|
|
|
|
current.prev = null;
|
|
current = current.next;
|
|
};
|
|
|
|
this.head = null;
|
|
this.tail = null;
|
|
|
|
this.map.clear();
|
|
}
|
|
};
|
|
|
|
module.exports = DoubleLinkedList; |