Skip to content

Instantly share code, notes, and snippets.

@christianscott
Created April 15, 2019 14:24
Show Gist options
  • Save christianscott/696194f6db5513988f2603f8ed7ff4de to your computer and use it in GitHub Desktop.
Save christianscott/696194f6db5513988f2603f8ed7ff4de to your computer and use it in GitHub Desktop.
Doubly linked list - with reverse!
class DoublyLinkedList {
static from(array) {
const dll = new DoublyLinkedList()
for (const val of array) {
dll.append(val)
}
return dll
}
constructor() {
this.head = null
this.tail = null
this.size = 0
}
append(value) {
this.size++
if (this.tail == null) {
this.head = this.tail = { value, prev: null, next: null }
} else {
const oldTail = this.tail
const node = { value, prev: oldTail, next: null }
oldTail.next = node
this.tail = node
}
return this
}
prepend(value) {
this.size++
if (this.tail == null) {
this.head = this.tail = { value, prev: null, next: null }
} else {
const oldHead = this.head
const node = { value, prev: null, next: oldHead }
oldHead.prev = node
this.head = node
}
return this
}
insert(at, value) {
if (at === 0) {
return this.prepend(value)
}
if (at === this.size) {
return this.append(value)
}
if (at > this.size) {
throw new TypeError('insert index out of bounds')
}
this.walk((node, i) => {
if (i === at - 1) {
const oldNext = node.next
node.next = oldNext.prev = { value, next: oldNext, prev: node }
}
})
return this
}
removeAt(at) {
this.walk((node, i) => {
if (i === at) {
node.prev.next = node.next
node.next.prev = node.prev
}
})
return this
}
reverse() {
let current = this.tail
while (current != null) {
[current.next, current.prev] = [current.prev, current.next]
current = current.next
}
[this.head, this.tail] = [this.tail, this.head]
return this
}
equals(other) {
if (this.size !== other.size) { // assuming we can rely on this...
return false
}
if (this === other) {
return true
}
let thisCurrent = this.head,
otherCurrent = other.head
while (thisCurrent != null && otherCurrent != null) {
if (thisCurrent.value !== otherCurrent.value) {
return false
}
thisCurrent = thisCurrent.next
otherCurrent = otherCurrent.next
}
return true
}
walk(callback) {
let current = this.head,
i = 0
while (current != null) {
callback(current, i++)
current = current.next
}
return this
}
prettyPrint() {
let output = ''
this.walk(node => {
if (node.next != null) {
output += `${node.value} <-> `
} else {
output += `${node.value}`
}
})
return output
}
}
console.log(
DoublyLinkedList
.from([1, 2, 3, 4])
.equals(
DoublyLinkedList
.from([4, 3, 2, 1])
.reverse()
)
)
console.log(
DoublyLinkedList
.from(['πŸŒ‘', 'πŸŒ’', 'πŸŒ“', 'πŸŒ”', 'πŸŒ•'])
.reverse()
.prettyPrint()
)
console.log(
DoublyLinkedList
.from(['πŸ˜„', 'πŸ˜„', '😭', 'πŸ˜„', 'πŸ˜„', 'πŸ˜„'])
.removeAt(2)
.prettyPrint()
)
for (let i = 0; i < 5; i++) {
let dll = DoublyLinkedList
.from(['πŸ₯Ά', 'πŸ₯Ά', 'πŸ₯Ά', 'πŸ₯Ά'])
.insert(i, 'πŸ₯΅')
console.log(dll.prettyPrint())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment