Skip to content

Instantly share code, notes, and snippets.

@divmain
Created November 11, 2013 16:47
Show Gist options
  • Save divmain/7416304 to your computer and use it in GitHub Desktop.
Save divmain/7416304 to your computer and use it in GitHub Desktop.
doubly linked list
var Node = function() {
this.data = arguments[0];
this.next = arguments[1] === undefined ? null : arguments[1];
this.prev = arguments[2] === undefined ? null : arguments[2];
};
var LinkedList = function() {
this.head = null;
this.tail = null;
this.length = 0;
}
LinkedList.prototype.append = function(data) {
if (this.tail === null) {
this.tail = this.head = new Node(data);
} else {
originalTail = this.tail;
originalTail.next = this.tail = new Node(data, null, originalTail);
}
this.length++;
};
LinkedList.prototype.prepend = function(data) {
if (this.tail === null) {
this.tail = this.head = new Node(data);
} else {
originalHead = this.head;
originalHead.prev = this.head = new Node(data, this.head, null);
}
this.length++;
};
LinkedList.prototype.pop_front = function() {
var head = this.head;
if (!head) return undefined;
if (!head.next) {
this.head = null;
this.tail = null;
} else {
this.head = this.head.next;
this.head.prev = null;
}
this.length--;
return head.data;
}
LinkedList.prototype.pop_back = function() {
var tail = this.tail;
if (!tail) return undefined;
if (!tail.prev) {
this.head = null;
this.tail = null;
} else {
this.tail = this.tail.prev;
this.tail.next = null;
}
this.length--;
return tail.data;
};
LinkedList.prototype.popAt = function(index) {
if (index === 0) {
return this.pop_front();
} else if (index === this.length - 1) {
if (this.length === 0) throw "Error: empty list.";
return this.pop_back();
} else {
node = this.nodeAt(index);
node.prev.next = node.next;
node.next.prev = node.prev;
}
this.length--;
return node.data;
};
LinkedList.prototype.nodeAt = function(index) {
var current;
if (index === 0) {
current = this.head;
} else if (index === this.length - 1) {
current = this.tail;
} else if (index > 0) {
current = this.head;
for (i=0; i<index; i++) {
if (current.next === null) { throw "Index is out of range."; };
current = current.next;
}
} else {
current = this.tail;
for (i=-1; i>index; i--) {
if (current.prev === null) { throw "Index is out of range."; };
current = current.prev;
}
}
return current;
};
LinkedList.prototype.insertAt = function(index, data) {
if (index === 0) {
this.prepend(data);
} else if (index === this.length - 1) {
this.append(data);
} else {
node = this.nodeAt(index);
newNode = new Node(data, node, node.prev);
newNode.prev.next = newNode;
newNode.next.prev = newNode;
}
this.length++
};
LinkedList.prototype.delete = function(index) {
this.popAt(index);
};
LinkedList.prototype.print = function() {
var output = [];
var current = this.head;
while (current != null) {
output.push(current.data);
current = current.next;
}
console.log(output);
return output;
};
var ll = new LinkedList();
ll.append("hello");
ll.append("class");
ll.delete(1);
ll.append("world");
ll.prepend("oh!");
ll.print();
// [ "oh!", "hello", "world" ]
var mm = new LinkedList();
mm.append("hello0");
mm.append("hello1");
mm.append("hello2");
mm.append("hello3");
mm.insertAt(2, "hello1.5");
mm.insertAt(-2, "hello1.75");
mm.print();
// [ 'hello0', 'hello1', 'hello1.5', 'hello1.75', 'hello2', 'hello3' ]
console.log(mm.nodeAt(0).data);
// hello0
console.log(mm.nodeAt(-2).data);
// hello2
console.log(mm.popAt(-2));
// hello2
console.log(mm.popAt(0));
// hello0
mm.print();
// [ 'hello1', 'hello1.5', 'hello1.75', 'hello3' ]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment