data-structures
Version:
JavaScript data structures written in CoffeeScript.
1,756 lines (1,482 loc) • 47.1 kB
JavaScript
require=(function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0](function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({"data-structures":[function(require,module,exports){
module.exports=require('EerzU6');
},{}],"EerzU6":[function(require,module,exports){
(function() {
module.exports = {
Graph: require('./Graph'),
Heap: require('./Heap'),
LinkedList: require('./LinkedList'),
Map: require('./Map'),
Queue: require('./Queue'),
RedBlackTree: require('./RedBlackTree'),
Trie: require('./Trie')
};
}).call(this);
},{"./Graph":1,"./Heap":2,"./LinkedList":3,"./Map":4,"./Queue":5,"./RedBlackTree":6,"./Trie":7}],1:[function(require,module,exports){
/*
Graph implemented as a modified incidence list. O(1) for every typical
operation, even `removeNode()` ( **O(1) amortized** ).
## Overview example:
```js
var graph = new Graph;
graph.addNode('A'); // => a node object. For more info, log the output or check
// the documentation for addNode
graph.addNode('B');
graph.addNode('C');
graph.addEdge('A', 'C'); // => an edge object
graph.addEdge('A', 'B');
graph.getEdge('B', 'A'); // => undefined. Directed edge!
graph.getEdge('A', 'B'); // => the edge object previously added
graph.getInEdgesOf('B'); // => array of edge objects, in this case only one;
// connecting A to B
graph.getOutEdgesOf('A'); // => array of edge objects, one to B and one to C
graph.getAllEdgesOf('A'); // => all the in and out edges. Edge directed toward
// the node itself are only counted once
forEachNode(function(nodeObject) {
console.log(node);
});
forEachEdge(function(edgeObject) {
console.log(edgeObject);
});
graph.removeNode('C'); // => 'C'. The edge between A and C also removed
graph.removeEdge('A', 'B'); // => the edge object removed
```
## Properties:
- nodeSize: total number of nodes.
- edgeSize: total number of edges.
*/
(function() {
var Graph;
Graph = (function() {
function Graph() {
this._nodes = {};
this.nodeSize = 0;
this.edgeSize = 0;
}
Graph.prototype.addNode = function(id) {
/*
The `id` is a unique identifier for the node, and should **not** change
after it's added. It will be used for adding, retrieving and deleting
related edges too.
Note that JavaScript's object hashes the id `'2'` and `2` to the same key,
so please stick with one single id data type for a same graph.
_Returns:_ the node object. Feel free to attach additional custom properties
on it for graph algorithms' needs. **Undefined if node id already exists**,
as to avoid accidental overrides.
*/
if (!this._nodes[id]) {
this.nodeSize++;
return this._nodes[id] = {
_id: id,
_outEdges: {},
_inEdges: {},
_edgeCount: 0
};
}
};
Graph.prototype.getNode = function(id) {
/*
_Returns:_ the node object. Feel free to attach additional custom properties
on it for graph algorithms' needs.
*/
return this._nodes[id];
};
Graph.prototype.removeNode = function(id) {
/*
_Returns:_ the node object removed, or undefined if it didn't exist in the
first place.
*/
var nodeToRemove;
nodeToRemove = this._nodes[id];
if (!nodeToRemove) {
} else {
this.edgeSize -= this._nodes[id]._edgeCount;
this.nodeSize--;
delete this._nodes[id];
return nodeToRemove;
}
};
Graph.prototype.addEdge = function(fromId, toId, weight) {
var edgeToAdd, fromNode, toNode;
if (weight == null) {
weight = 1;
}
/*
`fromId` and `toId` are the node id specified when it was created using
`addNode()`. `weight` is optional and defaults to 1. Ignoring it effectively
makes this an unweighted graph. Under the hood, `weight` is just a normal
property of the edge object.
_Returns:_ the edge object created. Feel free to attach additional custom
properties on it for graph algorithms' needs. **Or undefined** if the nodes
of id `fromId` or `toId` aren't found, or if an edge already exists between
the two nodes.
*/
if (this.getEdge(fromId, toId)) {
return;
}
fromNode = this._nodes[fromId];
toNode = this._nodes[toId];
if (!fromNode || !toNode) {
return;
}
edgeToAdd = {
_fromId: fromId,
_toId: toId,
weight: weight
};
fromNode._outEdges[toId] = edgeToAdd;
toNode._inEdges[fromId] = edgeToAdd;
fromNode._edgeCount++;
this.edgeSize++;
if (fromNode !== toNode) {
toNode._edgeCount++;
}
return edgeToAdd;
};
Graph.prototype.getEdge = function(fromId, toId) {
/*
_Returns:_ the edge object, or undefined if the nodes of id `fromId` or
`toId` aren't found.
*/
var fromNode, toNode;
fromNode = this._nodes[fromId];
toNode = this._nodes[toId];
if (!fromNode && !toNode) {
} else if (!fromNode) {
if (toNode._inEdges[fromId]) {
delete toNode._inEdges[fromId];
}
} else if (!toNode) {
if (fromNode._outEdges[toId]) {
delete fromNode._outEdges[toId];
}
} else {
if (!fromNode._outEdges[toId] && toNode._inEdges[fromId]) {
delete toNode._inEdges[fromId];
} else if (!toNode._inEdges[fromId] && fromNode._outEdges[toId]) {
delete fromNode._outEdges[toId];
} else {
return fromNode._outEdges[toId];
}
}
};
Graph.prototype.removeEdge = function(fromId, toId) {
/*
_Returns:_ the edge object removed, or undefined of edge wasn't found.
*/
var edgeToDelete, fromNode, toNode;
fromNode = this._nodes[fromId];
toNode = this._nodes[toId];
edgeToDelete = this.getEdge(fromId, toId);
if (!edgeToDelete) {
return;
}
delete fromNode._outEdges[toId];
delete toNode._inEdges[fromId];
this.edgeSize--;
return edgeToDelete;
};
Graph.prototype.getInEdgesOf = function(nodeId) {
/*
_Returns:_ an array of edge objects that are directed toward the node, or
empty array if none exists.
*/
var edge, fromId, inEdges, toNode;
toNode = this._nodes[nodeId];
if (!toNode) {
return [];
}
inEdges = [];
for (fromId in toNode._inEdges) {
edge = this.getEdge(fromId, nodeId);
if (edge) {
inEdges.push(edge);
}
}
return inEdges;
};
Graph.prototype.getOutEdgesOf = function(nodeId) {
/*
_Returns:_ an array of edge objects that go out of the node, or empty array
if none exists.
*/
var edge, fromNode, outEdges, toId;
fromNode = this._nodes[nodeId];
if (!fromNode) {
return [];
}
outEdges = [];
for (toId in fromNode._outEdges) {
edge = this.getEdge(nodeId, toId);
if (edge) {
outEdges.push(edge);
}
}
return outEdges;
};
Graph.prototype.getAllEdgesOf = function(nodeId) {
/*
**Note:** not the same as concatenating `getInEdgesOf()` and
`getOutEdgesOf()`. Some nodes might have an edge pointing toward itself.
This method solves that duplication.
_Returns:_ an array of edge objects linked to the node, no matter if they're
outgoing or coming. Duplicate edge created by self-pointing nodes are
removed. Only one copy stays. Empty array if node has no edge.
*/
var i, inEdges, outEdges, selfEdge, _i, _ref, _ref1;
inEdges = this.getInEdgesOf(nodeId);
outEdges = this.getOutEdgesOf(nodeId);
if (inEdges.length === 0) {
return outEdges;
}
selfEdge = this.getEdge(nodeId, nodeId);
if (selfEdge) {
for (i = _i = 0, _ref = inEdges.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
if (inEdges[i] === selfEdge) {
_ref1 = [inEdges[inEdges.length - 1], inEdges[i]], inEdges[i] = _ref1[0], inEdges[inEdges.length - 1] = _ref1[1];
inEdges.pop();
break;
}
}
}
return inEdges.concat(outEdges);
};
Graph.prototype.forEachNode = function(operation) {
/*
Traverse through the graph in an arbitrary manner, visiting each node once.
Pass a function of the form `fn(nodeObject)`.
_Returns:_ undefined.
*/
var nodeId, nodeObject, _ref;
_ref = this._nodes;
for (nodeId in _ref) {
nodeObject = _ref[nodeId];
operation(nodeObject);
}
};
Graph.prototype.forEachEdge = function(operation) {
/*
Traverse through the graph in an arbitrary manner, visiting each edge once.
Pass a function of the form `fn(edgeObject)`.
_Returns:_ undefined.
*/
var edgeObject, nodeId, nodeObject, toId, _ref, _ref1;
_ref = this._nodes;
for (nodeId in _ref) {
nodeObject = _ref[nodeId];
_ref1 = nodeObject._outEdges;
for (toId in _ref1) {
edgeObject = _ref1[toId];
operation(edgeObject);
}
}
};
return Graph;
})();
module.exports = Graph;
}).call(this);
},{}],2:[function(require,module,exports){
/*
Minimum heap, i.e. smallest node at root.
**Note:** does not accept null or undefined. This is by design. Those values
cause comparison problems and might report false negative during extraction.
## Overview example:
```js
var heap = new Heap([5, 6, 3, 4]);
heap.add(10); // => 10
heap.removeMin(); // => 3
heap.peekMin(); // => 4
```
## Properties:
- size: total number of items.
*/
(function() {
var Heap, _leftChild, _parent, _rightChild;
Heap = (function() {
function Heap(dataToHeapify) {
var i, item, _i, _j, _len, _ref;
if (dataToHeapify == null) {
dataToHeapify = [];
}
/*
Pass an optional array to be heapified. Takes only O(n) time.
*/
this._data = [void 0];
for (_i = 0, _len = dataToHeapify.length; _i < _len; _i++) {
item = dataToHeapify[_i];
if (item != null) {
this._data.push(item);
}
}
if (this._data.length > 1) {
for (i = _j = 2, _ref = this._data.length; 2 <= _ref ? _j < _ref : _j > _ref; i = 2 <= _ref ? ++_j : --_j) {
this._upHeap(i);
}
}
this.size = this._data.length - 1;
}
Heap.prototype.add = function(value) {
/*
**Remember:** rejects null and undefined for mentioned reasons.
_Returns:_ the value added.
*/
if (value == null) {
return;
}
this._data.push(value);
this._upHeap(this._data.length - 1);
this.size++;
return value;
};
Heap.prototype.removeMin = function() {
/*
_Returns:_ the smallest item (the root).
*/
var min;
if (this._data.length === 1) {
return;
}
this.size--;
if (this._data.length === 2) {
return this._data.pop();
}
min = this._data[1];
this._data[1] = this._data.pop();
this._downHeap();
return min;
};
Heap.prototype.peekMin = function() {
/*
Check the smallest item without removing it.
_Returns:_ the smallest item (the root).
*/
return this._data[1];
};
Heap.prototype._upHeap = function(index) {
var valueHolder, _ref;
valueHolder = this._data[index];
while (this._data[index] < this._data[_parent(index)] && index > 1) {
_ref = [this._data[_parent(index)], this._data[index]], this._data[index] = _ref[0], this._data[_parent(index)] = _ref[1];
index = _parent(index);
}
};
Heap.prototype._downHeap = function() {
var currentIndex, smallerChildIndex, _ref;
currentIndex = 1;
while (_leftChild(currentIndex < this._data.length)) {
smallerChildIndex = _leftChild(currentIndex);
if (smallerChildIndex < this._data.length - 1) {
if (this._data[_rightChild(currentIndex)] < this._data[smallerChildIndex]) {
smallerChildIndex = _rightChild(currentIndex);
}
}
if (this._data[smallerChildIndex] < this._data[currentIndex]) {
_ref = [this._data[currentIndex], this._data[smallerChildIndex]], this._data[smallerChildIndex] = _ref[0], this._data[currentIndex] = _ref[1];
currentIndex = smallerChildIndex;
} else {
break;
}
}
};
return Heap;
})();
_parent = function(index) {
return index >> 1;
};
_leftChild = function(index) {
return index << 1;
};
_rightChild = function(index) {
return (index << 1) + 1;
};
module.exports = Heap;
}).call(this);
},{}],3:[function(require,module,exports){
/*
Doubly Linked.
## Overview example:
```js
var list = new LinkedList([5, 4, 9]);
list.add(12); // => 12
list.head.next.value; // => 4
list.tail.value; // => 12
list.at(-1); // => 12
list.removeAt(2); // => 9
list.remove(4); // => 4
list.indexOf(5); // => 0
list.add(5, 1); // => 5. Second 5 at position 1.
list.indexOf(5, 1); // => 1
```
## Properties:
- head: first item.
- tail: last item.
- size: total number of items.
- item.value: value passed to the item when calling `add()`.
- item.prev: previous item.
- item.next: next item.
*/
(function() {
var LinkedList;
LinkedList = (function() {
function LinkedList(valuesToAdd) {
var value, _i, _len;
if (valuesToAdd == null) {
valuesToAdd = [];
}
/*
Can pass an array of elements to link together during `new LinkedList()`
initiation.
*/
this.head = {
prev: void 0,
value: void 0,
next: void 0
};
this.tail = {
prev: void 0,
value: void 0,
next: void 0
};
this.size = 0;
for (_i = 0, _len = valuesToAdd.length; _i < _len; _i++) {
value = valuesToAdd[_i];
this.add(value);
}
}
LinkedList.prototype.at = function(position) {
/*
Get the item at `position` (optional). Accepts negative index:
```js
myList.at(-1); // Returns the last element.
```
However, passing a negative index that surpasses the boundary will return
undefined:
```js
myList = new LinkedList([2, 6, 8, 3])
myList.at(-5); // Undefined.
myList.at(-4); // 2.
```
_Returns:_ item gotten, or undefined if not found.
*/
var currentNode, i, _i, _j, _ref;
if (!((-this.size <= position && position < this.size))) {
return;
}
position = this._adjust(position);
if (position * 2 < this.size) {
currentNode = this.head;
for (i = _i = 1; _i <= position; i = _i += 1) {
currentNode = currentNode.next;
}
} else {
currentNode = this.tail;
for (i = _j = 1, _ref = this.size - position - 1; _j <= _ref; i = _j += 1) {
currentNode = currentNode.prev;
}
}
return currentNode;
};
LinkedList.prototype.add = function(value, position) {
var currentNode, nodeToAdd, _ref, _ref1, _ref2;
if (position == null) {
position = this.size;
}
/*
Add a new item at `position` (optional). Defaults to adding at the end.
`position`, just like in `at()`, can be negative (within the negative
boundary). Position specifies the place the value's going to be, and the old
node will be pushed higher. `add(-2)` on list of size 7 is the same as
`add(5)`.
_Returns:_ item added.
*/
if (!((-this.size <= position && position <= this.size))) {
return;
}
nodeToAdd = {
value: value
};
position = this._adjust(position);
if (this.size === 0) {
this.head = nodeToAdd;
} else {
if (position === 0) {
_ref = [nodeToAdd, this.head, nodeToAdd], this.head.prev = _ref[0], nodeToAdd.next = _ref[1], this.head = _ref[2];
} else {
currentNode = this.at(position - 1);
_ref1 = [currentNode.next, nodeToAdd, nodeToAdd, currentNode], nodeToAdd.next = _ref1[0], (_ref2 = currentNode.next) != null ? _ref2.prev = _ref1[1] : void 0, currentNode.next = _ref1[2], nodeToAdd.prev = _ref1[3];
}
}
if (position === this.size) {
this.tail = nodeToAdd;
}
this.size++;
return value;
};
LinkedList.prototype.removeAt = function(position) {
var currentNode, valueToReturn, _ref;
if (position == null) {
position = this.size - 1;
}
/*
Remove an item at index `position` (optional). Defaults to the last item.
Index can be negative (within the boundary).
_Returns:_ item removed.
*/
if (!((-this.size <= position && position < this.size))) {
return;
}
if (this.size === 0) {
return;
}
position = this._adjust(position);
if (this.size === 1) {
valueToReturn = this.head.value;
this.head.value = this.tail.value = void 0;
} else {
if (position === 0) {
valueToReturn = this.head.value;
this.head = this.head.next;
this.head.prev = void 0;
} else {
currentNode = this.at(position);
valueToReturn = currentNode.value;
currentNode.prev.next = currentNode.next;
if ((_ref = currentNode.next) != null) {
_ref.prev = currentNode.prev;
}
if (position === this.size - 1) {
this.tail = currentNode.prev;
}
}
}
this.size--;
return valueToReturn;
};
LinkedList.prototype.remove = function(value) {
/*
Remove the item using its value instead of position. **Will remove the fist
occurrence of `value`.**
_Returns:_ the value, or undefined if value's not found.
*/
var currentNode;
if (value == null) {
return;
}
currentNode = this.head;
while (currentNode && currentNode.value !== value) {
currentNode = currentNode.next;
}
if (!currentNode) {
return;
}
if (this.size === 1) {
this.head.value = this.tail.value = void 0;
} else if (currentNode === this.head) {
this.head = this.head.next;
this.head.prev = void 0;
} else if (currentNode === this.tail) {
this.tail = this.tail.prev;
this.tail.next = void 0;
} else {
currentNode.prev.next = currentNode.next;
currentNode.next.prev = currentNode.prev;
}
this.size--;
return value;
};
LinkedList.prototype.indexOf = function(value, startingPosition) {
var currentNode, position;
if (startingPosition == null) {
startingPosition = 0;
}
/*
Find the index of an item, similarly to `array.indexOf()`. Defaults to start
searching from the beginning, by can start at another position by passing
`startingPosition`. This parameter can also be negative; but unlike the
other methods of this class, `startingPosition` (optional) can be as small
as desired; a value of -999 for a list of size 5 will start searching
normally, at the beginning.
**Note:** searches forwardly, **not** backwardly, i.e:
```js
var myList = new LinkedList([2, 3, 1, 4, 3, 5])
myList.indexOf(3, -3); // Returns 4, not 1
```
_Returns:_ index of item found, or -1 if not found.
*/
if (((this.head.value == null) && !this.head.next) || startingPosition >= this.size) {
return -1;
}
startingPosition = Math.max(0, this._adjust(startingPosition));
currentNode = this.at(startingPosition);
position = startingPosition;
while (currentNode) {
if (currentNode.value === value) {
break;
}
currentNode = currentNode.next;
position++;
}
if (position === this.size) {
return -1;
} else {
return position;
}
};
LinkedList.prototype._adjust = function(position) {
if (position < 0) {
return this.size + position;
} else {
return position;
}
};
return LinkedList;
})();
module.exports = LinkedList;
}).call(this);
},{}],4:[function(require,module,exports){
/*
Kind of a stopgap measure for the upcoming [JavaScript
Map](http://wiki.ecmascript.org/doku.php?id=harmony:simple_maps_and_sets)
**Note:** due to JavaScript's limitations, hashing something other than Boolean,
Number, String, Undefined, Null, RegExp, Function requires a hack that inserts a
hidden unique property into the object. This means `set`, `get`, `has` and
`delete` must employ the same object, and not a mere identical copy as in the
case of, say, a string.
## Overview example:
```js
var map = new Map({'alice': 'wonderland', 20: 'ok'});
map.set('20', 5); // => 5
map.get('20'); // => 5
map.has('alice'); // => true
map.delete(20) // => true
var arr = [1, 2];
map.add(arr, 'goody'); // => 'goody'
map.has(arr); // => true
map.has([1, 2]); // => false. Needs to compare by reference
map.forEach(function(key, value) {
console.log(key, value);
});
```
## Properties:
- size: The total number of `(key, value)` pairs.
*/
(function() {
var Map, SPECIAL_TYPE_KEY_PREFIX, _extractDataType, _isSpecialType,
__hasProp = {}.hasOwnProperty;
SPECIAL_TYPE_KEY_PREFIX = '_mapId_';
Map = (function() {
Map._mapIdTracker = 0;
Map._newMapId = function() {
return this._mapIdTracker++;
};
function Map(objectToMap) {
/*
Pass an optional object whose (key, value) pair will be hashed. **Careful**
not to pass something like {5: 'hi', '5': 'hello'}, since JavaScript's
native object behavior will crush the first 5 property before it gets to
constructor.
*/
var key, value;
this._content = {};
this._itemId = 0;
this._id = Map._newMapId();
this.size = 0;
for (key in objectToMap) {
if (!__hasProp.call(objectToMap, key)) continue;
value = objectToMap[key];
this.set(key, value);
}
}
Map.prototype.hash = function(key, makeHash) {
var propertyForMap, type;
if (makeHash == null) {
makeHash = false;
}
/*
The hash function for hashing keys is public. Feel free to replace it with
your own. The `makeHash` parameter is optional and accepts a boolean
(defaults to `false`) indicating whether or not to produce a new hash (for
the first use, naturally).
_Returns:_ the hash.
*/
type = _extractDataType(key);
if (_isSpecialType(key)) {
propertyForMap = SPECIAL_TYPE_KEY_PREFIX + this._id;
if (makeHash && !key[propertyForMap]) {
key[propertyForMap] = this._itemId++;
}
return propertyForMap + '_' + key[propertyForMap];
} else {
return type + '_' + key;
}
};
Map.prototype.set = function(key, value) {
/*
_Returns:_ value.
*/
if (!this.has(key)) {
this.size++;
}
this._content[this.hash(key, true)] = [value, key];
return value;
};
Map.prototype.get = function(key) {
/*
_Returns:_ value corresponding to the key, or undefined if not found.
*/
var _ref;
return (_ref = this._content[this.hash(key)]) != null ? _ref[0] : void 0;
};
Map.prototype.has = function(key) {
/*
Check whether a value exists for the key.
_Returns:_ true or false.
*/
return this.hash(key) in this._content;
};
Map.prototype["delete"] = function(key) {
/*
Remove the (key, value) pair.
_Returns:_ **true or false**. Unlike most of this library, this method
doesn't return the deleted value. This is so that it conforms to the future
JavaScript `map.delete()`'s behavior.
*/
var hashedKey;
hashedKey = this.hash(key);
if (hashedKey in this._content) {
delete this._content[hashedKey];
if (_isSpecialType(key)) {
delete key[SPECIAL_TYPE_KEY_PREFIX + this._id];
}
this.size--;
return true;
}
return false;
};
Map.prototype.forEach = function(operation) {
/*
Traverse through the map. Pass a function of the form `fn(key, value)`.
_Returns:_ undefined.
*/
var key, value, _ref;
_ref = this._content;
for (key in _ref) {
value = _ref[key];
operation(value[1], value[0]);
}
};
return Map;
})();
_isSpecialType = function(key) {
var simpleHashableTypes, simpleType, type, _i, _len;
simpleHashableTypes = ['Boolean', 'Number', 'String', 'Undefined', 'Null', 'RegExp', 'Function'];
type = _extractDataType(key);
for (_i = 0, _len = simpleHashableTypes.length; _i < _len; _i++) {
simpleType = simpleHashableTypes[_i];
if (type === simpleType) {
return false;
}
}
return true;
};
_extractDataType = function(type) {
return Object.prototype.toString.apply(type).match(/\[object (.+)\]/)[1];
};
module.exports = Map;
}).call(this);
},{}],5:[function(require,module,exports){
/*
Amortized O(1) dequeue!
## Overview example:
```js
var queue = new Queue([1, 6, 4]);
queue.enqueue(10); // => 10
queue.dequeue(); // => 1
queue.dequeue(); // => 6
queue.dequeue(); // => 4
queue.peek(); // => 10
queue.dequeue(); // => 10
queue.peek(); // => undefined
```
## Properties:
- size: The total number of items.
*/
(function() {
var Queue;
Queue = (function() {
function Queue(initialArray) {
if (initialArray == null) {
initialArray = [];
}
/*
Pass an optional array to be transformed into a queue. The item at index 0
is the first to be dequeued.
*/
this._content = initialArray;
this._dequeueIndex = 0;
this.size = this._content.length;
}
Queue.prototype.enqueue = function(item) {
/*
_Returns:_ the item.
*/
this.size++;
this._content.push(item);
return item;
};
Queue.prototype.dequeue = function() {
/*
_Returns:_ the dequeued item.
*/
var itemToDequeue;
if (this.size === 0) {
return;
}
this.size--;
itemToDequeue = this._content[this._dequeueIndex];
this._dequeueIndex++;
if (this._dequeueIndex * 2 > this._content.length) {
this._content = this._content.slice(this._dequeueIndex);
this._dequeueIndex = 0;
}
return itemToDequeue;
};
Queue.prototype.peek = function() {
/*
Check the next item to be dequeued, without removing it.
_Returns:_ the item.
*/
return this._content[this._dequeueIndex];
};
return Queue;
})();
module.exports = Queue;
}).call(this);
},{}],6:[function(require,module,exports){
/*
Credit to Wikipedia's article on [Red-black
tree](http://en.wikipedia.org/wiki/Red–black_tree)
**Note:** doesn't handle duplicate entries, undefined and null. This is by
design.
## Overview example:
```js
var rbt = new RedBlackTree([7, 5, 1, 8]);
rbt.add(2); // => 2
rbt.add(10); // => 10
rbt.has(5); // => true
rbt.peekMin(); // => 1
rbt.peekMax(); // => 10
rbt.removeMin(); // => 1
rbt.removeMax(); // => 10
rbt.remove(8); // => 8
```
## Properties:
- size: The total number of items.
*/
(function() {
var BLACK, NODE_FOUND, NODE_TOO_BIG, NODE_TOO_SMALL, RED, RedBlackTree, STOP_SEARCHING, _findNode, _grandParentOf, _isLeft, _leftOrRight, _peekMaxNode, _peekMinNode, _siblingOf, _uncleOf;
NODE_FOUND = 0;
NODE_TOO_BIG = 1;
NODE_TOO_SMALL = 2;
STOP_SEARCHING = 3;
RED = 1;
BLACK = 2;
RedBlackTree = (function() {
function RedBlackTree(valuesToAdd) {
var value, _i, _len;
if (valuesToAdd == null) {
valuesToAdd = [];
}
/*
Pass an optional array to be turned into binary tree. **Note:** does not
accept duplicate, undefined and null.
*/
this._root;
this.size = 0;
for (_i = 0, _len = valuesToAdd.length; _i < _len; _i++) {
value = valuesToAdd[_i];
if (value != null) {
this.add(value);
}
}
}
RedBlackTree.prototype.add = function(value) {
/*
Again, make sure to not pass a value already in the tree, or undefined, or
null.
_Returns:_ value added.
*/
var currentNode, foundNode, nodeToInsert, _ref;
if (value == null) {
return;
}
this.size++;
nodeToInsert = {
value: value,
_color: RED
};
if (!this._root) {
this._root = nodeToInsert;
} else {
foundNode = _findNode(this._root, function(node) {
if (value === node.value) {
return NODE_FOUND;
} else {
if (value < node.value) {
if (node._left) {
return NODE_TOO_BIG;
} else {
nodeToInsert._parent = node;
node._left = nodeToInsert;
return STOP_SEARCHING;
}
} else {
if (node._right) {
return NODE_TOO_SMALL;
} else {
nodeToInsert._parent = node;
node._right = nodeToInsert;
return STOP_SEARCHING;
}
}
}
});
if (foundNode != null) {
return;
}
}
currentNode = nodeToInsert;
while (true) {
if (currentNode === this._root) {
currentNode._color = BLACK;
break;
}
if (currentNode._parent._color === BLACK) {
break;
}
if (((_ref = _uncleOf(currentNode)) != null ? _ref._color : void 0) === RED) {
currentNode._parent._color = BLACK;
_uncleOf(currentNode)._color = BLACK;
_grandParentOf(currentNode)._color = RED;
currentNode = _grandParentOf(currentNode);
continue;
}
if (!_isLeft(currentNode) && _isLeft(currentNode._parent)) {
this._rotateLeft(currentNode._parent);
currentNode = currentNode._left;
} else if (_isLeft(currentNode) && !_isLeft(currentNode._parent)) {
this._rotateRight(currentNode._parent);
currentNode = currentNode._right;
}
currentNode._parent._color = BLACK;
_grandParentOf(currentNode)._color = RED;
if (_isLeft(currentNode)) {
this._rotateRight(_grandParentOf(currentNode));
} else {
this._rotateLeft(_grandParentOf(currentNode));
}
break;
}
return value;
};
RedBlackTree.prototype.has = function(value) {
/*
_Returns:_ true or false.
*/
var foundNode;
foundNode = _findNode(this._root, function(node) {
if (value === node.value) {
return NODE_FOUND;
} else if (value < node.value) {
return NODE_TOO_BIG;
} else {
return NODE_TOO_SMALL;
}
});
if (foundNode) {
return true;
} else {
return false;
}
};
RedBlackTree.prototype.peekMin = function() {
/*
Check the minimum value without removing it.
_Returns:_ the minimum value.
*/
var _ref;
return (_ref = _peekMinNode(this._root)) != null ? _ref.value : void 0;
};
RedBlackTree.prototype.peekMax = function() {
/*
Check the maximum value without removing it.
_Returns:_ the maximum value.
*/
var _ref;
return (_ref = _peekMaxNode(this._root)) != null ? _ref.value : void 0;
};
RedBlackTree.prototype.remove = function(value) {
/*
_Returns:_ the value removed, or undefined if the value's not found.
*/
var foundNode;
foundNode = _findNode(this._root, function(node) {
if (value === node.value) {
return NODE_FOUND;
} else if (value < node.value) {
return NODE_TOO_BIG;
} else {
return NODE_TOO_SMALL;
}
});
if (!foundNode) {
return;
}
this._removeNode(this._root, foundNode);
this.size--;
return value;
};
RedBlackTree.prototype.removeMin = function() {
/*
_Returns:_ smallest item removed, or undefined if tree's empty.
*/
var nodeToRemove, valueToReturn;
nodeToRemove = _peekMinNode(this._root);
if (!nodeToRemove) {
return;
}
valueToReturn = nodeToRemove.value;
this._removeNode(this._root, nodeToRemove);
return valueToReturn;
};
RedBlackTree.prototype.removeMax = function() {
/*
_Returns:_ biggest item removed, or undefined if tree's empty.
*/
var nodeToRemove, valueToReturn;
nodeToRemove = _peekMaxNode(this._root);
if (!nodeToRemove) {
return;
}
valueToReturn = nodeToRemove.value;
this._removeNode(this._root, nodeToRemove);
return valueToReturn;
};
RedBlackTree.prototype._removeNode = function(root, node) {
var sibling, successor, _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7;
if (node._left && node._right) {
successor = _peekMinNode(node._right);
node.value = successor.value;
node = successor;
}
successor = node._left || node._right;
if (!successor) {
successor = {
color: BLACK,
_right: void 0,
_left: void 0,
isLeaf: true
};
}
successor._parent = node._parent;
if ((_ref = node._parent) != null) {
_ref[_leftOrRight(node)] = successor;
}
if (node._color === BLACK) {
if (successor._color === RED) {
successor._color = BLACK;
if (!successor._parent) {
this._root = successor;
}
} else {
while (true) {
if (!successor._parent) {
if (!successor.isLeaf) {
this._root = successor;
} else {
this._root = void 0;
}
break;
}
sibling = _siblingOf(successor);
if ((sibling != null ? sibling._color : void 0) === RED) {
successor._parent._color = RED;
sibling._color = BLACK;
if (_isLeft(successor)) {
this._rotateLeft(successor._parent);
} else {
this._rotateRight(successor._parent);
}
}
sibling = _siblingOf(successor);
if (successor._parent._color === BLACK && (!sibling || (sibling._color === BLACK && (!sibling._left || sibling._left._color === BLACK) && (!sibling._right || sibling._right._color === BLACK)))) {
if (sibling != null) {
sibling._color = RED;
}
if (successor.isLeaf) {
successor._parent[_leftOrRight(successor)] = void 0;
}
successor = successor._parent;
continue;
}
if (successor._parent._color === RED && (!sibling || (sibling._color === BLACK && (!sibling._left || ((_ref1 = sibling._left) != null ? _ref1._color : void 0) === BLACK) && (!sibling._right || ((_ref2 = sibling._right) != null ? _ref2._color : void 0) === BLACK)))) {
if (sibling != null) {
sibling._color = RED;
}
successor._parent._color = BLACK;
break;
}
if ((sibling != null ? sibling._color : void 0) === BLACK) {
if (_isLeft(successor) && (!sibling._right || sibling._right._color === BLACK) && ((_ref3 = sibling._left) != null ? _ref3._color : void 0) === RED) {
sibling._color = RED;
if ((_ref4 = sibling._left) != null) {
_ref4._color = BLACK;
}
this._rotateRight(sibling);
} else if (!_isLeft(successor) && (!sibling._left || sibling._left._color === BLACK) && ((_ref5 = sibling._right) != null ? _ref5._color : void 0) === RED) {
sibling._color = RED;
if ((_ref6 = sibling._right) != null) {
_ref6._color = BLACK;
}
this._rotateLeft(sibling);
}
break;
}
sibling = _siblingOf(successor);
sibling._color = successor._parent._color;
if (_isLeft(successor)) {
sibling._right._color = BLACK;
this._rotateRight(successor._parent);
} else {
sibling._left._color = BLACK;
this._rotateLeft(successor._parent);
}
}
}
}
if (successor.isLeaf) {
return (_ref7 = successor._parent) != null ? _ref7[_leftOrRight(successor)] = void 0 : void 0;
}
};
RedBlackTree.prototype._rotateLeft = function(node) {
var _ref, _ref1;
if ((_ref = node._parent) != null) {
_ref[_leftOrRight(node)] = node._right;
}
node._right._parent = node._parent;
node._parent = node._right;
node._right = node._right._left;
node._parent._left = node;
if ((_ref1 = node._right) != null) {
_ref1._parent = node;
}
if (node._parent._parent == null) {
return this._root = node._parent;
}
};
RedBlackTree.prototype._rotateRight = function(node) {
var _ref, _ref1;
if ((_ref = node._parent) != null) {
_ref[_leftOrRight(node)] = node._left;
}
node._left._parent = node._parent;
node._parent = node._left;
node._left = node._left._right;
node._parent._right = node;
if ((_ref1 = node._left) != null) {
_ref1._parent = node;
}
if (node._parent._parent == null) {
return this._root = node._parent;
}
};
return RedBlackTree;
})();
_isLeft = function(node) {
return node === node._parent._left;
};
_leftOrRight = function(node) {
if (_isLeft(node)) {
return '_left';
} else {
return '_right';
}
};
_findNode = function(startingNode, comparator) {
var comparisonResult, currentNode, foundNode;
currentNode = startingNode;
foundNode = void 0;
while (currentNode) {
comparisonResult = comparator(currentNode);
if (comparisonResult === NODE_FOUND) {
foundNode = currentNode;
break;
}
if (comparisonResult === NODE_TOO_BIG) {
currentNode = currentNode._left;
} else if (comparisonResult === NODE_TOO_SMALL) {
currentNode = currentNode._right;
} else if (comparisonResult === STOP_SEARCHING) {
break;
}
}
return foundNode;
};
_peekMinNode = function(startingNode) {
return _findNode(startingNode, function(node) {
if (node._left) {
return NODE_TOO_BIG;
} else {
return NODE_FOUND;
}
});
};
_peekMaxNode = function(startingNode) {
return _findNode(startingNode, function(node) {
if (node._right) {
return NODE_TOO_SMALL;
} else {
return NODE_FOUND;
}
});
};
_grandParentOf = function(node) {
var _ref;
return (_ref = node._parent) != null ? _ref._parent : void 0;
};
_uncleOf = function(node) {
if (!_grandParentOf(node)) {
return;
}
if (_isLeft(node._parent)) {
return _grandParentOf(node)._right;
} else {
return _grandParentOf(node)._left;
}
};
_siblingOf = function(node) {
if (_isLeft(node)) {
return node._parent._right;
} else {
return node._parent._left;
}
};
module.exports = RedBlackTree;
}).call(this);
},{}],7:[function(require,module,exports){
/*
Good for fast insertion/removal/lookup of strings.
## Overview example:
```js
var trie = new Trie(['bear', 'beer']);
trie.add('hello'); // => 'hello'
trie.add('helloha!'); // => 'helloha!'
trie.has('bears'); // => false
trie.longestPrefixOf('beatrice'); // => 'bea'
trie.wordsWithPrefix('hel'); // => ['hello', 'helloha!']
trie.remove('beers'); // => undefined. 'beer' still exists
trie.remove('Beer') // => undefined. Case-sensitive
trie.remove('beer') // => 'beer'. Removed
```
## Properties:
- size: The total number of words.
*/
(function() {
var Queue, Trie, WORD_END, _hasAtLeastNChildren;
Queue = require('./Queue');
WORD_END = 'end';
Trie = (function() {
function Trie(words) {
var word, _i, _len;
if (words == null) {
words = [];
}
/*
Pass an optional array of strings to be inserted initially.
*/
this._root = {};
this.size = 0;
for (_i = 0, _len = words.length; _i < _len; _i++) {
word = words[_i];
this.add(word);
}
}
Trie.prototype.add = function(word) {
/*
Add a whole string to the trie.
_Returns:_ the word added. Will return undefined (without adding the value)
if the word passed is null or undefined.
*/
var currentNode, letter, _i, _len;
if (word == null) {
return;
}
this.size++;
currentNode = this._root;
for (_i = 0, _len = word.length; _i < _len; _i++) {
letter = word[_i];
if (currentNode[letter] == null) {
currentNode[letter] = {};
}
currentNode = currentNode[letter];
}
currentNode[WORD_END] = true;
return word;
};
Trie.prototype.has = function(word) {
/*
__Returns:_ true or false.
*/
var currentNode, letter, _i, _len;
if (word == null) {
return false;
}
currentNode = this._root;
for (_i = 0, _len = word.length; _i < _len; _i++) {
letter = word[_i];
if (currentNode[letter] == null) {
return false;
}
currentNode = currentNode[letter];
}
if (currentNode[WORD_END]) {
return true;
} else {
return false;
}
};
Trie.prototype.longestPrefixOf = function(word) {
/*
Find all words containing the prefix. The word itself counts as a prefix.
```js
var trie = new Trie;
trie.add('hello');
trie.longestPrefixOf('he'); // 'he'
trie.longestPrefixOf('hello'); // 'hello'
trie.longestPrefixOf('helloha!'); // 'hello'
```
_Returns:_ the prefix string, or empty string if no prefix found.
*/
var currentNode, letter, prefix, _i, _len;
if (word == null) {
return '';
}
currentNode = this._root;
prefix = '';
for (_i = 0, _len = word.length; _i < _len; _i++) {
letter = word[_i];
if (currentNode[letter] == null) {
break;
}
prefix += letter;
currentNode = currentNode[letter];
}
return prefix;
};
Trie.prototype.wordsWithPrefix = function(prefix) {
/*
Find all words containing the prefix. The word itself counts as a prefix.
**Watch out for edge cases.**
```js
var trie = new Trie;
trie.wordsWithPrefix(''); // []. Check later case below.
trie.add('');
trie.wordsWithPrefix(''); // ['']
trie.add('he');
trie.add('hello');
trie.add('hell');
trie.add('bear');
trie.add('z');
trie.add('zebra');
trie.wordsWithPrefix('hel'); // ['hell', 'hello']
```
_Returns:_ an array of strings, or empty array if no word found.
*/
var accumulatedLetters, currentNode, letter, node, queue, subNode, words, _i, _len, _ref;
if (prefix == null) {
return [];
}
(prefix != null) || (prefix = '');
words = [];
currentNode = this._root;
for (_i = 0, _len = prefix.length; _i < _len; _i++) {
letter = prefix[_i];
currentNode = currentNode[letter];
if (currentNode == null) {
return [];
}
}
queue = new Queue();
queue.enqueue([currentNode, '']);
while (queue.size !== 0) {
_ref = queue.dequeue(), node = _ref[0], accumulatedLetters = _ref[1];
if (node[WORD_END]) {
words.push(prefix + accumulatedLetters);
}
for (letter in node) {
subNode = node[letter];
queue.enqueue([subNode, accumulatedLetters + letter]);
}
}
return words;
};
Trie.prototype.remove = function(word) {
/*
_Returns:_ the string removed, or undefined if the word in its whole doesn't
exist. **Note:** this means removing `beers` when only `beer` exists will
return undefined and conserve `beer`.
*/
var currentNode, i, letter, prefix, _i, _j, _len, _ref;
if (word == null) {
return;
}
currentNode = this._root;
prefix = [];
for (_i = 0, _len = word.length; _i < _len; _i++) {
letter = word[_i];
if (currentNode[letter] == null) {
return;
}
currentNode = currentNode[letter];
prefix.push([letter, currentNode]);
}
if (!currentNode[WORD_END]) {
return;
}
this.size--;
delete currentNode[WORD_END];
if (_hasAtLeastNChildren(currentNode, 1)) {
return word;
}
for (i = _j = _ref = prefix.length - 1; _ref <= 1 ? _j <= 1 : _j >= 1; i = _ref <= 1 ? ++_j : --_j) {
if (!_hasAtLeastNChildren(prefix[i][1], 1)) {
delete prefix[i - 1][1][prefix[i][0]];
} else {
break;
}
}
if (!_hasAtLeastNChildren(this._root[prefix[0][0]], 1)) {
delete this._root[prefix[0][0]];
}
return word;
};
return Trie;
})();
_hasAtLeastNChildren = function(node, n) {
var child, childCount;
if (n === 0) {
return true;
}
childCount = 0;
for (child in node) {
childCount++;
if (childCount >= n) {
return true;
}
}
return false;
};
module.exports = Trie;
}).call(this);
},{"./Queue":5}]},{},["EerzU6"])
;