7fife-backend/node_modules/sylvester/lib/node-sylvester/linkedlist.js

135 lines
3.2 KiB
JavaScript

// Copyright (c) 2011, Chris Umbel, James Coglan
// LinkedList class - required for Polygon class.
function LinkedList() {}
LinkedList.prototype = {
length: 0,
first: null,
last: null,
each: function(fn) {
var node = this.first, n = this.length;
for (var i = 0; i < n; i++) {
fn(node, i);
node = node.next;
}
},
at: function(i) {
if (!(i >= 0 && i < this.length)) { return null; }
var node = this.first;
while (i--) { node = node.next; }
return node;
},
randomNode: function() {
var n = Math.floor(Math.random() * this.length);
return this.at(n);
},
toArray: function() {
var arr = [], node = this.first, n = this.length;
while (n--) {
arr.push(node.data || node);
node = node.next;
}
return arr;
}
};
LinkedList.Node = function(data) {
this.prev = null; this.next = null;
this.data = data;
};
LinkedList.Circular = function() {};
LinkedList.Circular.Methods = {
append: function(node) {
if (this.first === null) {
node.prev = node;
node.next = node;
this.first = node;
this.last = node;
} else {
node.prev = this.last;
node.next = this.first;
this.first.prev = node;
this.last.next = node;
this.last = node;
}
this.length++;
},
prepend: function(node) {
if (this.first === null) {
this.append(node);
return;
} else {
node.prev = this.last;
node.next = this.first;
this.first.prev = node;
this.last.next = node;
this.first = node;
}
this.length++;
},
insertAfter: function(node, newNode) {
newNode.prev = node;
newNode.next = node.next;
node.next.prev = newNode;
node.next = newNode;
if (newNode.prev == this.last) { this.last = newNode; }
this.length++;
},
insertBefore: function(node, newNode) {
newNode.prev = node.prev;
newNode.next = node;
node.prev.next = newNode;
node.prev = newNode;
if (newNode.next == this.first) { this.first = newNode; }
this.length++;
},
remove: function(node) {
if (this.length > 1) {
node.prev.next = node.next;
node.next.prev = node.prev;
if (node == this.first) { this.first = node.next; }
if (node == this.last) { this.last = node.prev; }
} else {
this.first = null;
this.last = null;
}
node.prev = null;
node.next = null;
this.length--;
},
withData: function(data) {
var nodeFromStart = this.first, nodeFromEnd = this.last, n = Math.ceil(this.length / 2);
while (n--) {
if (nodeFromStart.data == data) { return nodeFromStart; }
if (nodeFromEnd.data == data) { return nodeFromEnd; }
nodeFromStart = nodeFromStart.next;
nodeFromEnd = nodeFromEnd.prev;
}
return null;
}
};
LinkedList.Circular.prototype = new LinkedList;
for (var method in LinkedList.Circular.Methods) {
LinkedList.Circular.prototype[method] = LinkedList.Circular.Methods[method];
}
LinkedList.Circular.fromArray = function(list, useNodes) {
var linked = new LinkedList.Circular();
var n = list.length;
while (n--) { linked.prepend(useNodes ? new LinkedList.Node(list[n]) : list[n]); }
return linked;
};
module.exports = LinkedList;