diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..7b33e33 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,9 @@ +// 将设置放入此文件中以覆盖默认值和用户设置。 +{ + // 定义函数的左大括号是否放置在新的一行。 + "typescript.format.placeOpenBraceOnNewLineForFunctions": true, + // 定义控制块的左括号是否放置在新的一行。 + "typescript.format.placeOpenBraceOnNewLineForControlBlocks": true, + "javascript.format.placeOpenBraceOnNewLineForFunctions": true, + "javascript.format.placeOpenBraceOnNewLineForControlBlocks": true +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..52606f4 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,23 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "type": "typescript", + "tsconfig": "lib\\tsconfig.json", + "option": "watch", + "problemMatcher": [ + "$tsc-watch" + ] + }, + { + "type": "typescript", + "tsconfig": "Tests\\tsconfig.json", + "option": "watch", + "problemMatcher": [ + "$tsc-watch" + ] + } + ] +} \ No newline at end of file diff --git a/DataStructures.js b/DataStructures.js deleted file mode 100644 index 01cd4a8..0000000 --- a/DataStructures.js +++ /dev/null @@ -1,5449 +0,0 @@ -/** - * Interface for managing a generic data structure. - * @constructor - * @interface - */ -function Aggregate() { - -} - -/** - * Returns the iterator relative to the aggregate. - * @abstract - * @return {Iterator} The iterator. - */ -Aggregate.prototype.getIterator = function () { -}; - -/** - * Interface for managing an iterator for an aggregate. - * @constructor - * @interface - */ -function Iterator() { - -} - -/** - * Moves the iterator to the first position of the aggregate. - * @abstract - * @return {void} - */ -Iterator.prototype.first = function () { - -}; - -/** - * Moves the iterator to the next item. - * @abstract - * @return {void} - */ -Iterator.prototype.next = function () { - -}; - -/** - * Moves the iterator to the last position of the aggregate. - * @abstract - * @return {void} - */ -Iterator.prototype.last = function () { - -}; - -/** - * Moves the iterator to the previous item. - * @abstract - * @return {void} - */ -Iterator.prototype.previous = function () { - -}; - -/** - * Checks if the iterator is out of the bounds of the aggregate. - * @abstract - * @return {boolean} It return true if the iterator is out of the bounds of the aggregate, otherwise false. - */ -Iterator.prototype.isDone = function () { - -}; - -/** - * Returns the item stored at the position pointed by the iterator. - * @abstract - * @return {*} The item stored or undefined if it's out of the bounds. - */ -Iterator.prototype.getItem = function () { - -}; - -/** - * Class for managing a binary search tree. - * @constructor - */ -function BSTree() { - /** - * The root of the tree. - * @type {BSNode|null} - */ - this.root = null; -} - -/** - * Returns the iterator relative to the aggregate. - * @return {Iterator} The iterator. - */ -BSTree.prototype.getIterator = function () { - return new BSTreeIterator(this); -}; - -/** - * Inserts the item relatives to the key value in the tree. - * @param key {number} The key to store. - * @param item {*} The item to store. - * @return {void} - */ -BSTree.prototype.insert = function (key, item) { - var node = new BSNode(key, item); - var p = this.root; - for (var n = this.root; n;) { - p = n; - if (key < n.key) - n = n.left; - else - n = n.right; - } - node.parent = p; - if (!p) - this.root = node; - else if (key < p.key) - p.left = node; - else - p.right = node; -}; - -/** - * Searches the item relatives to the key. - * @param key {Number} The key to find. - * @param [node = root] {BSNode} The node from which start the search. - * @return {*} The item found or undefined if there isn't the key in the tree. - */ -BSTree.prototype.search = function (key, node) { - node = node || this.root; - while (node && key !== node.key) - if (key < node.key) - node = node.left; - else - node = node.right; - if (node) - return node.item; - return undefined; -}; - -/** - * Gets the item relatives to the minimum key stored in the tree. - * @param [node = root] {Node} The node from which start the search. - * @return {BSNode} The node found. - */ -BSTree.prototype.minimum = function (node) { - node = node || this.root; - while (node && node.left) - node = node.left; - return node; -}; - -/** - * Gets the item relatives to the maximum key stored in the tree. - * @param [node = root] {Node} The node from which start the search. - * @return {BSNode} The node found. - */ -BSTree.prototype.maximum = function (node) { - node = node || this.root; - while (node && node.right) - node = node.right; - return node; -}; - -/** - * Gets the node with the key next to the param node key. - * @param node {BSNode} The node of which search the successor. - * @return {BSNode} The node found. - */ -BSTree.prototype.successor = function (node) { - if (node.right) - return this.minimum(node.right); - var parent = node.parent; - while (parent && node === parent.right) { - node = parent; - parent = parent.parent; - } - return parent; -}; - -/** - * Gets the node with the key previous to the param node key. - * @param node {BSNode} The node of which search the predecessor. - * @return {BSNode} The node found. - */ -BSTree.prototype.predecessor = function (node) { - if (node.left) - return this.maximum(node.left); - var parent = node.parent; - while (parent && node === parent.left) { - node = parent; - parent = parent.parent; - } - return parent; -}; - -/** - * Deletes the node from the tree. - * @param node {BSNode} The node to delete. - * @return {void} - */ -BSTree.prototype.deleteNode = function (node) { - if (!node.left && !node.right) { - if (node === this.root) - this.root = null; - else if (node.parent.left === node) - node.parent.left = null; - else - node.parent.right = null; - } else if (node.left && node.right) { - var next = this.successor(node); - node.key = next.key; - node.item = next.item; - if (next.parent.left === next) - next.parent.left = null; - else - next.parent.right = null; - } else { - if (node.right) { - if (node === this.root) { - this.root = node.right; - node.right.parent = null; - } else { - node.parent.right = node.right; - node.right.parent = node.parent; - } - } else { - if (node === this.root) { - this.root = node.left; - node.left.parent = null; - } else { - node.parent.left = node.left; - node.left.parent = node.parent; - } - } - } -}; - -/** - * Class that implements the iterator for a binary search tree. - * @param aggregate {BSTree} The aggregate to scan. - * @constructor - */ -function BSTreeIterator(aggregate) { - /** - * The aggregate relates to this iterator. - * @type {BSTree} - */ - this.aggregate = aggregate; - - /** - * The pointer to the position. - * @type {BSNode|null} - */ - this.pointer = null; -} - -/** - * Moves the iterator to the first position of the aggregate. - * @return {void} - */ -BSTreeIterator.prototype.first = function () { - this.pointer = this.aggregate.minimum(); -}; - -/** - * Moves the iterator to the next item. - * @return {void} - */ -BSTreeIterator.prototype.next = function () { - this.pointer = this.aggregate.successor(this.pointer); -}; - -/** - * Moves the iterator to the last position of the aggregate. - * @return {void} - */ -BSTreeIterator.prototype.last = function () { - this.pointer = this.aggregate.maximum(); -}; - -/** - * Moves the iterator to the previous item. - * @return {void} - */ -BSTreeIterator.prototype.previous = function () { - this.pointer = this.aggregate.predecessor(this.pointer); -}; - -/** - * Checks if the iterator is out of the bounds of the aggregate. - * @return {boolean} It return true if the iterator is out of the bounds of the aggregate, otherwise false. - */ -BSTreeIterator.prototype.isDone = function () { - return !this.pointer; -}; - -/** - * Returns the item stored at the position pointed by the iterator. - * @return {*} The item stored or undefined if it's out of the bounds. - */ -BSTreeIterator.prototype.getItem = function () { - return this.pointer.item; -}; - -/** - * Returns the node stored at the position pointed by the iterator. - * @return {BSNode|null} The node stored or null if it's out of the bounds. - */ -BSTreeIterator.prototype.getNode = function () { - return this.pointer; -}; - -/** - * Class for managing a B-Tree. - * @param minimumDegree {number} The minimum number of keys of a node. - * @constructor - */ -function BTree(minimumDegree) { - /** - * The root of the tree. - * @type {BNode} - */ - this.root = new BNode(); - - /** - * The minimum number of the keys of a node. - * @type {number} - */ - this.t = minimumDegree; - - /** - * The number of items stored in the tree. - * @type {number} - */ - this.size = 0; -} - -/** - * Returns the iterator relative to the aggregate. - * @return {Iterator} The iterator. - */ -BTree.prototype.getIterator = function () { - return new BTreeIterator(this); -}; - -/** - * Inserts the item relatives to the key value in the tree. - * @param key {number} The key to store. - * @param item {*} The item to store. - * @return {void} - */ -BTree.prototype.insert = function (key, item) { - var node = this.root; - if (node.keys.length === 2 * this.t - 1) { - var newNode = new BNode(); - newNode.childs.push(node); - this.root = newNode; - this.splitChild(newNode, 0); - node = newNode; - } - this.size++; - this.insertNonFull(node, key, item); -}; - -/** - * Inserts the new node in the right position if the node is not full. - * @param node {BNode} The node from which start to check the insertion. - * @param key {number} The key to store. - * @param item {*} The item to store. - * @return {void} - */ -BTree.prototype.insertNonFull = function (node, key, item) { - while (node) { - var i = node.keys.length - 1; - if (!node.childs.length) { - for (; i > -1 && key < node.keys[i]; i--) { - node.keys[i + 1] = node.keys[i]; - node.items[i + 1] = node.items[i]; - } - node.keys[i + 1] = key; - node.items[i + 1] = item; - return; - } else { - var j = 0; - i++; - while (j < i) { - var m = Math.floor((j + i) / 2); - if (key <= node.keys[m]) - i = m; - else - j = m + 1; - } - if (node.childs[j].keys.length === 2 * this.t - 1) { - this.splitChild(node, j); - if (key > node.keys[j]) - j++; - } - node = node.childs[j]; - } - } -}; - -/** - * Searches the item relatives to the key that satisfy the condition represented by the callback function. - * @param key {Number} The key to find. - * @param [node = root] {RBNode} The node from which start the search. - * @param [callback = function(node,index){return(node.keys[index]===key);}] The condition to satisfy. The callback must accept the current node to check and optionally the position of the key. - * @return {*} The item found or undefined if there isn't the key in the tree. - */ -BTree.prototype.search = function (key, node, callback) { - node = node || this.root; - callback = callback || function (node, index) { - return node.keys[index] === key; - }; - while (node) { - var n = node.keys.length; - var i = 0, j = n; - while (i < j) { - var m = Math.floor((i + j) / 2); - if (key <= node.keys[m]) - j = m; - else - i = m + 1; - } - if (i < n && callback(node, i)) - return node.items[i]; - else if (!node.childs.length) - return undefined; - else - node = node.childs[i]; - } -}; - -/** - * Splits the child of the node at the position index. - * @param node {BNode} The parent of the child to split. - * @param index {number} The position of the child to split. - * @return {void} - */ -BTree.prototype.splitChild = function (node, index) { - var newNode = new BNode(); - var child = node.childs[index]; - //copy of the last t - 1 keys and items in the new node - for (var i = 0; i < this.t - 1; i++) { - newNode.keys[i] = child.keys[i + this.t]; - newNode.items[i] = child.items[i + this.t]; - } - if (child.childs.length) - //copy of the last t child in the new node - for (var j = 0; j < this.t; j++) - newNode.childs[j] = child.childs[j + this.t]; - //shift the children from index + 1 position - for (var l = node.keys.length; l > index; l--) - node.childs[l + 1] = node.childs[l]; - //set the index position as the position t of the child - node.childs[index + 1] = newNode; - //shift the keys and the items from index position - for (var k = node.keys.length - 1; k > index - 1; k--) { - node.keys[k + 1] = node.keys[k]; - node.items[k + 1] = node.items[k]; - } - node.keys[index] = child.keys[this.t - 1]; - node.items[index] = child.items[this.t - 1]; - //remove keys, items and child in the old node. - child.keys.splice(child.keys.length - this.t); - child.items.splice(child.items.length - this.t); - child.childs.splice(child.childs.length - this.t); -}; - -/** - * Deletes the key from the tree. - * @param key {*} The key to delete. - * @return {void} - */ -BTree.prototype.deleteKey = function (key) { - if (this.root.keys.length) { - this.deleteNonMin(this.root, key); - if (!this.root.keys.length && this.root.childs.length) - this.root = this.root.childs[0]; - this.size--; - } -}; - -/** - * Deletes a node that's a number of keys greater than the minimum for a node. - * @param node {BNode} The node to delete. - * @param key {number} The key to delete. - * @return {void} - */ -BTree.prototype.deleteNonMin = function (node, key) { - var i = 0, j = node.keys.length; - while (i < j) { - var m = Math.floor((i + j) / 2); - if (key <= node.keys[m]) - j = m; - else - i = m + 1; - } - //key is in the node - if (i < node.keys.length && key === node.keys[i]) { - //the node is a leaf - if (!node.childs.length) { - //remove the key - for (j = i + 1; j < node.keys.length; j++) { - node.keys[j - 1] = node.keys[j]; - node.items[j - 1] = node.items[j]; - } - node.keys.pop(); - node.items.pop(); - } else { - //the node is not a leaf - //the node has the minimum number of keys - if (node.childs[i].length === this.t - 1) { - //increase the number of the keys of the node - this.augmentChild(node, i); - if (i === node.keys.length + 1) - i--; - } - //check if the key is moved in the child - if (node.keys[i] !== key) - this.deleteNonMin(node.childs[i], key); - else - this.deleteMax(node, i); - } - //the key is not in the node - } else { - //check if the child i has the minimum number of keys - if (node.childs[i].keys.length === this.t - 1) { - this.augmentChild(node, i); - if (i === node.keys.length + 2) - i--; - } - this.deleteNonMin(node.childs[i], key); - } -}; - -/** - * Deletes a node that have the maximum number of keys for node. - * @param node {BNode} The node to delete. - * @param index {number} The key to delete in the node. - * @return {void} - */ -BTree.prototype.deleteMax = function (node, index) { - var child = node.childs[index]; - var goAhead = true; - while (goAhead) { - if (!child.childs.length) { - node.keys[index] = child.keys[child.keys.length - 1]; - node.items[index] = child.items[child.items.length - 1]; - child.keys.pop(); - child.items.pop(); - goAhead = false; - } else { - var last = child.childs[child.keys.length]; - if (last.keys.length === this.t - 1) - this.augmentChild(child, child.keys.length); - child = child.childs[child.keys.length]; - } - } -}; - -/** - * Augments the number of keys stored in the node preserving the order. - * @param node {BNode} The node to delete. - * @param index {number} The index of the position to augment. - * @return {void} - */ -BTree.prototype.augmentChild = function (node, index) { - var child = node.childs[index]; - var brother; - if (index) - brother = node.childs[index - 1]; - if (index && brother.keys.length > this.t - 1) { - if (child.childs.length) { - for (var j = this.keys.length + 1; j > 0; j--) - child.childs[j] = child.childs[j - 1]; - child.childs[0] = brother.childs[brother.keys.length]; - for (var i = child.keys.length; i > 0; i--) { - child.keys[i] = child.keys[i - 1]; - child.items[i] = child.items[i - 1]; - } - child.keys[0] = node.keys[index - 1]; - child.items[0] = node.items[index - 1]; - node.keys[index - 1] = brother.keys[brother.keys.length - 1]; - node.items[index - 1] = brother.items[brother.items.length - 1]; - } - } else { - if (index < node.keys.length) - brother = node.childs[index + 1]; - if (index < node.keys.length && brother.keys.length > this.t - 1) { - if (brother.childs.length) { - child.childs[child.keys.length + 1] = brother.childs[0]; - for (var l = 1; l < brother.keys.length + 1; l++) - brother.childs[l - 1] = brother.childs[l]; - brother.childs.pop(); - } - child.keys[child.keys.length] = node.keys[index]; - child.items[child.items.length] = node.items[index]; - node.keys[index] = brother.keys[0]; - node.items[index] = brother.items[0]; - for (var k = 1; k < brother.keys.length; k++) { - brother.keys[k - 1] = brother.keys[k]; - brother.items[k - 1] = brother.items[k]; - } - brother.keys.pop(); - brother.items.pop(); - } else { - if (index < node.keys.length) { - child.keys[this.t - 1] = node.keys[index]; - child.items[this.t - 1] = node.items[index]; - for (var m = index + 2; m < node.keys.length + 1; m++) - node.childs[m - 1] = node.childs[m]; - node.childs.pop(); - for (var n = index + 1; n < node.keys.length; n++) { - node.keys[n - 1] = node.keys[n]; - node.items[n - 1] = node.items[n]; - } - node.keys.pop(); - node.items.pop(); - if (brother.childs.length) - for (var y = 0; y < brother.keys.length + 1; y++) - child.childs[this.t + y] = brother.childs[y]; - for (var x = 0; x < brother.keys.length; x++) { - child.keys[x + this.t] = brother.keys[x]; - child.items[x + this.t] = brother.items[x]; - } - } else { - if (brother.childs.length) - for (var w = 0; w < child.keys.length + 1; w++) - brother.childs[this.t + w] = child.childs[w]; - brother.keys[this.t - 1] = node.keys[node.keys.length - 1]; - brother.items[this.t - 1] = node.items[node.keys.length - 1]; - for (var z = 0; z < child.keys.length; z++) { - brother.keys[z + this.t] = child.keys[z]; - brother.items[z + this.t] = child.items[z]; - } - } - } - } -}; - -/** - * Checks if the tree contains the key. - * @param key {number} The key to find. - * @param [callback = function(node,index){return(node.keys[index]===key);}] The condition to satisfy. The callback must accept the current node to check and optionally the position of the key. - * @return {boolean} True if the tree contains the key. - */ -BTree.prototype.contains = function (key, callback) { - return this.search(key, null, callback) !== undefined; -}; - -/** - * Checks if the tree contains a node that satisfy the condition represented by the callback function. - * This method check all the tree avoiding the binary search. - * @param callback {function} The condition to satisfy. The callback must accept the current node to check. - * @return {boolean} True if the tree contains the node that satisfy the condition, false otherwise. - */ -BTree.prototype.fullContains = function (callback) { - var key = this.minimumKey(); - while (key !== null && !callback(this.search(key))) - key = this.successor(key); - return key !== null; -}; - -/** - * Gets the key next to the param node key. - * @param key {number} The key of which search the successor. - * @param [node = root] The node from start the search of the successor. - * @return {number} The key found. - */ -BTree.prototype.successor = function (key, node) { - node = node || this.root; - var i = 0, j = node.keys.length; - //search the key in the node - while (i < j) { - var m = Math.floor((i + j) / 2); - if (key <= node.keys[m]) - j = m; - else - i = m + 1; - } - //check if the key has been found - if (node.keys[i] === key) - //in this case the successor is the next key - i++; - //if it's a leaf - if (!node.childs.length) { - //check if the key hasn't been found - if (i > node.keys.length - 1) - return null; - else - return node.keys[i]; - } - //if it's not a leaf check if the successor is in the i-child - var successor = this.successor(key, node.childs[i]); - //if it's not in the child and has been found a key then return it - if (successor === null && i < node.keys.length) - return node.keys[i]; - //return the value of the successor even if it's null - return successor; -}; - -/** - * Gets the key previous to the param key. - * @param key {number} The key of which search the predecessor. - * @param [node = root] The node from start the search of the predecessor. - * @return {number} The key found. - */ -BTree.prototype.predecessor = function (key, node) { - node = node || this.root; - var i = 0, j = node.keys.length; - //search the key in the node - while (i < j) { - var m = Math.floor((i + j) / 2); - if (key <= node.keys[m]) - j = m; - else - i = m + 1; - } - i--; - //check if the node is a leaf - if (!node.childs.length) { - //check if a predecessor has been found - if (i < 0) - return null; - else - return node.keys[i]; - } - var predecessor = this.predecessor(key, node.childs[i + 1]); - if (predecessor === null && key > node.keys[0]) { - return node.keys[i]; - } - return predecessor; -}; - -/** - * Gets the minimum key stored in the tree. - * @return {number} The key found. - */ -BTree.prototype.minimumKey = function () { - var node = this.root; - while (node.childs.length) - node = node.childs[0]; - if (node) - return node.keys[0]; - return null; -}; - -/** - * Gets the maximum key stored in the tree. - * @return {number} The key found. - */ -BTree.prototype.maximumKey = function () { - var node = this.root; - while (node.childs.length) - node = node.childs[node.childs.length - 1]; - if (node) - return node.keys[node.keys.length - 1]; - return null; -}; - -/** - * Gets the item relatives to the minimum key stored in the tree. - * @return {number} The item found. - */ -BTree.prototype.minimum = function () { - var node = this.root; - while (node.childs.length) - node = node.childs[0]; - return node.items[0]; -}; - -/** - * Gets the item relatives to the maximum key stored in the tree. - * @return {node} The item found. - */ -BTree.prototype.maximum = function () { - var node = this.root; - while (node.childs.length) - node = node.childs[node.childs.length - 1]; - return node.items[node.items.length - 1]; -}; - -/** - * Returns the size of the tree. - * @return {number} The size of the tree. - */ -BTree.prototype.getSize = function () { - return this.size; -}; - -/** - * Checks if the tree is empty. - * @return {boolean} True if the tree is empty, false otherwise. - */ -BTree.prototype.isEmpty = function () { - return !this.size; -}; - -/** - * Executes the callback function for each item of the tree. - * This method modifies the tree so if you don't need to modify it you must return the same item of the array. - * @param callback {function} The function to execute for each item. The function must accept the current item on which execute the function. - * @return {void} - */ -BTree.prototype.execute = function (callback) { - var node = arguments[1] || this.root; - for (var i = 0; i < node.items.length; i++) - node.items[i] = callback(node.items[i]); - for (var j = 0; j < node.childs.length; j++) - this.execute(callback, node.childs[j]); -}; - -/** - * Removes all the items stored in the tree. - * @return {void} - */ -BTree.prototype.clear = function () { - this.root = null; - this.size = 0; -}; - -/** - * Returns the items that satisfy the condition determined by the callback. - * @param callback {function} The function that implements the condition. - * @return {Array<*>} The array that contains the items that satisfy the condition. - */ -BTree.prototype.filter = function (callback) { - var result = []; - var node = arguments[1] || this.root; - for (var i = 0; i < node.items.length; i++) { - if (node.childs.length) - result = result.concat(this.filter(callback, node.childs[i])); - if (callback(node.items[i])) - result.push(node.items[i]); - } - if (node.childs.length) - result = result.concat(this.filter(callback, node.childs[node.childs.length - 1])); - return result; -}; - -/** - * Clones the tree into a new tree. - * @return {BTree} The tree cloned from this tree. - */ -BTree.prototype.clone = function () { - var tree = new BTree(this.t); - var it = this.getIterator(); - for (it.first(); !it.isDone(); it.next()) { - var item = it.getItem(); - if (item.clone) - item = item.clone(); - tree.insert(it.getKey(), item); - } - return tree; -}; - -/** - * Clones the tree into a new tree without cloning duplicated items. - * @return {BTree} The tree cloned from this tree. - */ -BTree.prototype.cloneDistinct = function () { - var tree = new BTree(this.t); - var it = this.getIterator(); - for (it.first(); !it.isDone(); it.next()) { - var callback = function (item) { - return item === it.getItem(); - }; - if (!tree.fullContains(callback)) { - if (it.getItem().cloneDistinct) - tree.insert(it.getKey(), it.getItem().cloneDistinct()); - else if (it.getItem().clone) - tree.insert(it.getKey(), it.getItem().clone()); - else - tree.insert(it.getKey(), it.getItem()); - } - } - return tree; -}; - -/** - * Transforms the tree into an array without preserving keys. - * @return {Array<*>} The array that represents the tree. - */ -BTree.prototype.toArray = function () { - var result = []; - var it = this.getIterator(); - for (it.first(); !it.isDone(); it.next()) - result.push(it.getItem()); - return result; -}; - -/** - * Returns the first position of the item in the tree. - * @param item {*} The item to search. - * @param [callback = function(item){return(it===item);}] The condition to satisfy. The callback must accept the current item to check. - * @return {number} The first position of the item. - */ -BTree.prototype.indexOf = function (item, callback) { - callback = callback || function (it) { - return it === item; - }; - var i = 0, key = this.minimumKey(); - while (key !== null) { - if (callback(this.search(key))) - return i; - key = this.successor(key); - i++; - } - return -1; -}; - -/** - * Returns the last position of the item in the tree. - * @param item {*} The item to search. - * @param [callback = function(item){return(it===item);}] The condition to satisfy. The callback must accept the current item to check. - * @return {number} The last position of the item. - */ -BTree.prototype.lastIndexOf = function (item, callback) { - callback = callback || function (it) { - return it === item; - }; - var i = this.size - 1, key = this.maximumKey(); - while (key !== null) { - if (callback(this.search(key))) - return i; - i--; - key = this.predecessor(key); - } - return -1; -}; - -/** - * Returns all the position in which the item has been found in the tree. - * @param item {*} The item to search. - * @param [callback = function(item){return(it===item);}] The condition to satisfy. The callback must accept the current item to check. - * @return {Array} The positions in which the item has been found. - */ -BTree.prototype.allIndexesOf = function (item, callback) { - callback = callback || function (it) { - return it === item; - }; - var i = 0, key = this.minimumKey(); - var indexes = []; - while (key !== null) { - if (callback(this.search(key))) - indexes.push(i); - i++; - key = this.successor(key); - } - return indexes; -}; - -/** - * Returns the item at the position index. - * @param index {number} The position of the item. - * @return {*} The item at the position. It's undefined if index isn't in the tree bounds. - */ -BTree.prototype.getItem = function (index) { - if (index < 0 || index > this.size - 1) - return undefined; - var key = this.minimum(); - for (var i = 0; i < index; i++) - key = this.successor(key); - return this.search(key); -}; - -/** - * Class that implements the iterator for a binary search tree. - * @param aggregate {BTree} The aggregate to scan. - * @constructor - */ -function BTreeIterator(aggregate) { - /** - * The aggregate relates to this iterator. - * @type {BTree} - */ - this.aggregate = aggregate; - - /** - * The pointer to the position. - * @type {number} - */ - this.pointer = null; -} - -/** - * Moves the iterator to the first position of the aggregate. - * @return {void} - */ -BTreeIterator.prototype.first = function () { - this.pointer = this.aggregate.minimumKey(); -}; - -/** - * Moves the iterator to the next item. - * @return {void} - */ -BTreeIterator.prototype.next = function () { - this.pointer = this.aggregate.successor(this.pointer); -}; - -/** - * Moves the iterator to the last position of the aggregate. - * @return {void} - */ -BTreeIterator.prototype.last = function () { - this.pointer = this.aggregate.maximumKey(); -}; - -/** - * Moves the iterator to the previous item. - * @return {void} - */ -BTreeIterator.prototype.previous = function () { - this.pointer = this.aggregate.predecessor(this.pointer); -}; - -/** - * Checks if the iterator is out of the bounds of the aggregate. - * @return {boolean} It return true if the iterator is out of the bounds of the aggregate, otherwise false. - */ -BTreeIterator.prototype.isDone = function () { - return this.pointer === null; -}; - -/** - * Returns the item stored at the position pointed by the iterator. - * @return {*} The item stored or undefined if it's out of the bounds. - */ -BTreeIterator.prototype.getItem = function () { - return this.aggregate.search(this.pointer); -}; - -/** - * Returns the key stored at the position pointed by the iterator. - * @return {number} The key stored or null if it's out of the bounds. - */ -BTreeIterator.prototype.getKey = function () { - return this.pointer; -}; - -/** - * Class for managing a circular buffer. - * @param size {Number} The size of the buffer. - * @constructor - */ -function CircularBuffer(size) { - /** - * The index of the position of the head of the buffer. - * @type {number} - */ - this.head = 0; - /** - * The index of the position of the tail of the buffer. - * @type {number} - */ - this.tail = 0; - /** - * The items stored in the buffer. - * @type {Array<*>} - */ - this.items = new Array(size); - /** - * Is true if buffer is empty, false otherwise. - * @type {boolean} - */ - this.empty = true; - /** - * Is false if buffer is full, false otherwise. - * @type {boolean} - */ - this.full = false; - /** - * The size of the buffer. - * @type {Number} - */ - this.size = size; -} - -/** - * Returns the iterator relative to the aggregate. - * @return {Iterator} The iterator. - */ -CircularBuffer.prototype.getIterator = function () { - return new CircularBufferIterator(this); -}; - -/** - * Writes the item at the head of the buffer. - * @param item {*} The item to write. - * @return {void} - */ -CircularBuffer.prototype.write = function (item) { - this.empty = false; - if (this.full) - //if buffer is full tail must be set forward - this.tail = (this.tail + 1) % this.size; - this.items[this.head] = item; - //head is set forward - this.head = (this.head + 1) % this.size; - if (this.tail === this.head) - this.full = true; -}; - -/** - * Frees the buffer between indexes from and to. - * If from > to, positions between from and the end of the buffer and between the start and to will be free. - * @param from {Number} The index from which start to free (inclusive index) - * @param to {Number} The index where stop to free (exclusive index) - * @return {void} - */ -CircularBuffer.prototype.free = function (from, to) { - if (from < 0) - from = 0; - if (from > this.size - 1) - from = this.size - 1; - if (to < 0) - to = 0; - if (to > this.size - 1) - to = this.size - 1; - //if from < to then will be free allocation between from and to - //otherwise will be free allocations between from and the end and between the start and to - for (var i = from; i < to; i = (i + 1) % this.size) - delete this.items[i]; - - //adjust the position of the tail and of the head - if (this.tail > from - 1 || this.tail < to) - if (this.tail < this.head) { - this.tail = (from - 1) % this.size; - } else { - this.tail = to; - } - if (this.head > from || this.head < to) - if (this.tail < this.head) { - this.head = to; - } else { - this.head = from; - } - //check if something is free - if (from !== to) - this.full = false; - //free could make buffer empty - for (var j = 0; j < this.size; j++) - if (this.items[j] !== undefined) { - this.empty = false; - return; - } - this.empty = true; -}; - -/** - * Frees all the buffer. - * @return {void} - */ -CircularBuffer.prototype.freeAll = function () { - for (var i = 0; i < this.size; i++) - delete this.items[i]; - this.empty = true; - this.head = 0; - this.tail = 0; -}; - -/** - * Reads the item stored at the position index. - * @param index {Number} The position of the item to read. - * @return {*} The item read. - */ -CircularBuffer.prototype.read = function (index) { - return this.items[index % this.size]; -}; - -/** - * Returns true if the buffer is empty, false otherwise. - * @return {boolean} - */ -CircularBuffer.prototype.isEmpty = function () { - return this.empty; -}; - -/** - * Returns true if the buffer is full, false otherwise. - * @return {boolean} - */ -CircularBuffer.prototype.isFull = function () { - return this.full; -}; - -/** - * Clones the circular buffer into a new circular buffer. - * @return {CircularBuffer} The circular buffer cloned from this circular buffer. - */ -CircularBuffer.prototype.clone = function () { - var buffer = new CircularBuffer(this.size); - buffer.head = this.head; - buffer.tail = this.tail; - for (var i = 0; i < this.items.length; i++) - buffer.items[i] = this.items[i]; - buffer.empty = this.empty; - buffer.full = this.full; - return buffer; -}; - -/** - * Resize the buffer. - * @param size {number} The new size of the buffer. - * @return {void} - */ -CircularBuffer.prototype.resize = function (size) { - if (this.size < size) { - if (this.head < this.tail + 1) { - for (var i = 0; i < this.head; i++) { - this.items[(i + this.size) % size] = this.items[i]; - delete this.items[i]; - } - this.head = (this.head + this.size) % size; - } - } else if (this.size > size) { - if (this.head < this.tail + 1) { - //check if the tail is after the size - var start = size; - if (this.tail > size - 1) { - start = this.tail; - this.tail = 0; - } - //the items stored must be shift to a valid position - var step = this.size - start; - for (var j = this.head - step - 1; j > start - 1 || j < this.head - step; j--) { - this.items[(j + step) % this.size] = this.items[j]; - if (!j) - j = this.size; - } - this.head = (this.head + step) % this.size; - } - } - this.size = size; -}; - -/** - * Class that implements the iterator for a circular buffer. - * @param aggregate {CircularBuffer} The aggregate to scan. - * @constructor - */ -function CircularBufferIterator(aggregate) { - /** - * The aggregate relates to this iterator. - * @type {CircularBuffer} - */ - this.aggregate = aggregate; - - /** - * The pointer to the position. - * @type {number|null} - */ - this.pointer = null; - /** - * Discriminator for full buffer - * @type {bool} - */ - this.start = true; -} - -/** - * Moves the iterator to the first position of the aggregate. - * @return {void} - */ -CircularBufferIterator.prototype.first = function () { - this.pointer = this.aggregate.tail; - this.start = true; -}; - -/** - * Moves the iterator to the next item. - * @return {void} - */ -CircularBufferIterator.prototype.next = function () { - this.pointer = (this.pointer + 1) % this.aggregate.size; - this.start = false; -}; - -/** - * Moves the iterator to the last position of the aggregate. - * @return {void} - */ -CircularBufferIterator.prototype.last = function () { - this.pointer = (this.aggregate.head - 1) % this.aggregate.size; - this.start = true; -}; - -/** - * Moves the iterator to the previous item. - * @return {void} - */ -CircularBufferIterator.prototype.previous = function () { - this.pointer = (this.pointer - 1) % this.aggregate.size; - this.start = false; -}; - -/** - * Checks if the iterator is out of the bounds of the aggregate. - * @return {boolean} It return true if the iterator is out of the bounds of the aggregate, otherwise false. - */ -CircularBufferIterator.prototype.isDone = function () { - return (this.pointer === this.aggregate.head && !this.start) || (this.pointer === this.aggregate.tail - 1) % this.aggregate.size || this.aggregate.isEmpty(); -}; - -/** - * Returns the item stored at the position pointed by the iterator. - * @return {*} The item stored or undefined if it's out of the bounds. - */ -CircularBufferIterator.prototype.getItem = function () { - return this.aggregate.read(this.pointer); -}; - -/** - * Class for managing a double linked list. - * @param {...*} [args] The items for initializing the list. - * @constructor - */ -function DoubleLinkedList(args) { - /** - * The first node of the list. - * @type {DLLNode|null} - */ - this.first = null; - /** - * The last node of the list. - * @type {DLLNode|null} - */ - this.last = null; - /** - * The length of the list. - * @type {number} - */ - this.length = 0; - //builds the list from the parameters of the constructor - this.fromArray(arguments); -} - -/** - * Returns the iterator relative to the aggregate. - * @return {Iterator} The iterator. - */ -DoubleLinkedList.prototype.getIterator = function () { - return new DoubleLinkedListIterator(this); -}; - -/** - * Adds an item at the head of the list. - * @param item {*} The item to add. - * @return {void} - */ -DoubleLinkedList.prototype.pushFront = function (item) { - var node = new DLLNode(item); - node.next = this.first; - this.first = node; - //link the next node to the new node - if (node.next) - node.next.previous = node; - else - this.last = node; - this.length++; -}; - -/** - * Adds an item at the tail of the list. - * @param item {*} The item to add. - * @return {void} - */ -DoubleLinkedList.prototype.pushBack = function (item) { - var node = new DLLNode(item); - node.previous = this.last; - this.last = node; - //link the previous node to the new node - if (node.previous) - node.previous.next = node; - else - this.first = node; - this.length++; -}; - -/** - * Removes the first item of the list. - * @return {*} The item removed. It's undefined if the list is empty. - */ -DoubleLinkedList.prototype.popFront = function () { - if (this.length) { - var node = this.first; - this.first = node.next; - if (node.next) - node.next.previous = null; - this.length--; - node.next = null; - return node.item; - } - return undefined; -}; - -/** - * Removes the last item of the list. - * @return {*} The item removed. It's undefined if the list is empty. - */ -DoubleLinkedList.prototype.popBack = function () { - if (this.length) { - var node = this.last; - this.last = node.previous; - if (node.previous) - node.previous.next = null; - this.length--; - node.previous = null; - return node.item; - } - return undefined; -}; - -/** - * Removes the first times items of the list. - * @param times {number} The number of times to repeat the popFront method. - * @return {*} The item removed. It's undefined if the list is empty. - */ -DoubleLinkedList.prototype.multiPopFront = function (times) { - var result = []; - for (var i = 0; i < times && this.length; i++) - result.push(this.popFront()); - return result; -}; - -/** - * Removes the last times items of the list. - * @param times {number} The number of times to repeat the popBack method. - * @return {*} The items removed. - */ -DoubleLinkedList.prototype.multiPopBack = function (times) { - var result = []; - for (var i = 0; i < times && this.length; i++) - result.push(this.popBack()); - return result; -}; - -/** - * Returns the first item of the list without remove it. - * @return {*} The item at the top of the list. It's undefined if the list is empty. - */ -DoubleLinkedList.prototype.peek = function () { - if (!this.length) - return undefined; - return this.first.item; -}; - -/** - * Adds the item at the index position. - * @param item {*} The item to add. - * @param index {number} The position where to add the item. If index is negative, the item won't be added. - * @return {void} - */ -DoubleLinkedList.prototype.addAt = function (item, index) { - if (index < 0) - return; - if (!index) { - this.pushFront(item); - return; - } - if (index === this.length) { - this.pushBack(item); - return; - } - var node = this.first; - if (!node && index > 0) - this.pushBack(undefined); - for (var i = 0; i < index - 1; i++, node = node.next) { - if (node === this.last) - this.pushBack(undefined); - } - if (node === this.last) - this.pushBack(item); - else if (node === this.first) - this.pushFront(item); - else { - var newNode = new DLLNode(item); - newNode.next = node.next; - newNode.previous = node; - node.next = newNode; - if (newNode.next) - newNode.next.previous = newNode; - this.length++; - } -}; - -/** - * Removes the item at the position index. - * @param index {Number} The position of the item to remove. - * @return {*} The item stored at the position index. It's undefined if the index is out of bounds. - */ -DoubleLinkedList.prototype.removeAt = function (index) { - if (index < 0 || index > this.length - 1) - return undefined; - if (index === 0) - return this.popFront(); - if (index === this.length - 1) - return this.popBack(); - var node = this.first; - for (; index > 0; index--) - node = node.next; - //now node is the node to remove - node.previous.next = node.next; - node.next.previous = node.previous; - node.next = null; - node.previous = null; - this.length--; - return node.item; -}; - -/** - * Removes the item from the list. - * @param item {*} The item to remove. - * @param [callback = function(item){return(it===item);}] The condition to satisfy. The callback must accept the current item to check. - * @return {void} - */ -DoubleLinkedList.prototype.remove = function (item, callback) { - callback = callback || function (it) { - return it === item; - }; - var node = this.first; - var previous = null; - while (node) { - if (callback(node.item)) { - if (node === this.first) - this.first = node.next; - if (node === this.last) - this.last = previous; - if (previous) { - previous.next = node.next; - if (node.next) - node.next.previous = previous; - } - return; - } - previous = node; - node = node.next; - } -}; - -/** - * Removes all the item from the list. - * @param item {*} The item to remove. - * @param [callback = function(item){return(it===item);}] The condition to satisfy. The callback must accept the current item to check. - * @return {void} - */ -DoubleLinkedList.prototype.removeAll = function (item, callback) { - callback = callback || function (it) { - return it === item; - }; - var node = this.first; - var previous = null; - while (node) { - if (callback(node.item)) { - if (node === this.first) - this.first = node.next; - if (node === this.last) - this.last = previous; - if (previous) { - previous.next = node.next; - if (node.next) - node.next.previous = previous; - } - } else - previous = node; - node = node.next; - } -}; - -/** - * Removes all the items stored from the from position to the to position. - * If from > to, the method will remove all the items up to the end. - * @param from {number} The position where start to remove the items. The from position is included. - * @param to {number} The position where stop to remove the items. The to position is included. - * @return {Array<*>} The items removed. - */ -DoubleLinkedList.prototype.removeSegment = function (from, to) { - var result = []; - if (to > -1 && from < this.length) { - if (from === 0) - return this.multiPopFront(to + 1); - if (to === this.length - 1 || from > to) - return this.multiPopBack(Math.max(to - from, this.length - from)).reverse(); - var node = this.first; - for (var i = 0; i < from - 1; i++) - node = node.next; - //now node is the node before the node to remove - //node to remove - var next = node.next; - for (var j = from; j < to + 1 && j < this.length; j++) { - result.push(next.item); - next = next.next; - } - this.length -= Math.min(to - from + 1, this.length - from); - node.next = next; - next.previous = node; - } - return result; -}; - -/** - * Changes the item stored in the index position. If the index is out of bound, the node won't be updated. - * @param index {number} The position of the node to modify. - * @param item {*} The new item stored in the node. - * @return {void} - */ -DoubleLinkedList.prototype.modifyAt = function (index, item) { - var node = this.getNode(index); - if (node) - node.item = item; -}; - -/** - * Removes all the items stored in the list. - * @return {void} - */ -DoubleLinkedList.prototype.clear = function () { - this.first = null; - this.last = null; - this.length = 0; -}; - -/** - * Checks if the list contains an item that satisfy the condition represented by the callback function. - * @param item {*} The item to find. - * @param [callback = function(item){return(it===item);}] The condition to satisfy. The callback must accept the current item to check. - * @return {boolean} True if the list contains the item that satisfy the condition, false otherwise. - */ -DoubleLinkedList.prototype.contains = function (item, callback) { - callback = callback || function (it) { - return it === item; - }; - var i = 0; - var node = this.first; - while (i < this.length && !callback(node.item)) { - i++; - node = node.next; - } - return i < this.length; -}; - -/** - * Executes the callback function for each item of the stack. - * This method modifies the list so if you don't need to modify it you must return the same item of the array. - * @param callback {function} The function to execute for each item. The function must accept the current item on which execute the function. - * @return {void} - */ -DoubleLinkedList.prototype.execute = function (callback) { - var node = this.first; - while (node) { - node.item = callback(node.item); - node = node.next; - } -}; - -/** - * Deletes the node from the list. - * @param node {DLLNode} The node to delete. - * @return {void} - */ -DoubleLinkedList.prototype.deleteNode = function (node) { - if (node === this.first) { - this.popFront(); - return; - } - if (node === this.last) { - this.popBack(); - return; - } - node.previous.next = node.next; - node.next.previous = node.previous; - this.length--; -}; - -/** - * Gets the node at the position index relative from the node. - * @param index {Number} The index, relative to the node, of the node to return. - * @param [node = first] {DLLNode} The node from which start the search. - * @return {DLLNode} The node at the position index. - */ -DoubleLinkedList.prototype.getNode = function (index, node) { - if (index < 0 || index > this.length - 1) - return undefined; - var m = Math.floor(this.length / 2); - //if the index is less than the middle, the search start from the head of the list, otherwise from the tail of the list - if (index < m || node) { - node = node || this.first; - for (; index > 0; index--) - node = node.next; - } else - for (index = this.length - index - 1, node = this.last; index > 0; index--) - node = node.previous; - return node; -}; - -/** - * Gets the item at the position index. - * @param index {Number} The position of the item. - * @return {*}. It's undefined if index isn't in the queue bounds. - */ -DoubleLinkedList.prototype.getItem = function (index) { - if (index < 0 || index > this.length - 1) - return undefined; - var node; - var m = Math.floor(this.length / 2); - if (index < m) //if the index is less than the middle, the search start from the head of the list, otherwise from the tail of the list - for (node = this.first; index > 0; index--) - node = node.next; - else - for (index = this.length - index - 1, node = this.last; index > 0; index--) - node = node.previous; - return node.item; -}; - -/** - * Sorts the list using web workers. - * Using this method is discouraged. Many web browser set a limit to the maximum number of workers instantiated. - * The items of the list, due to web workers implementation, will be serialized so they will lost own methods. - * @return {void} - */ -DoubleLinkedList.prototype.parallelSort = function () { - - var workers = []; - var _array = this.toArray(); - console.log(_array); - - function partialSort(_from, _to, _id) { - if (_from < _to) { - var m = Math.floor((_from + _to) / 2); - var workerLeft = new Worker("DoubleLinkedList/WorkerSort.js"); - var workerRight = new Worker("DoubleLinkedList/WorkerSort.js"); - workers.push(workerLeft); - workers.push(workerRight); - var length = workers.length; - workerLeft.postMessage({cmd: 'start', from: _from, to: m, worker: _id}); - workerRight.postMessage({cmd: 'start', from: m + 1, to: _to, worker: _id}); - partialSort(_from, m, length - 2); - partialSort(m + 1, _to, length - 1); - workerLeft.onmessage = function (event) { - var data = event.data; - switch (data.cmd) { - case 'finished': - workers[data.worker].postMessage({cmd: 'finished', array: _array}); - break; - case 'replace': - _array[data.index] = data.value; - break; - } - }; - workerRight.onmessage = function (event) { - var data = event.data; - switch (data.cmd) { - case 'finished': - workers[data.worker].postMessage({cmd: 'finished', array: _array}); - break; - case 'replace': - _array[data.index] = data.value; - break; - } - } - } - } - - var outerThis = this; - - var mainWorker = new Worker("DoubleLinkedList/WorkerSort.js"); - workers.push(mainWorker); - mainWorker.postMessage({cmd: 'start', from: 0, to: this.length - 1, worker: -1, array: _array}); - mainWorker.onmessage = function (event) { - var data = event.data; - switch (data.cmd) { - case 'finished': - outerThis.fromArray(_array); - console.log(outerThis); - break; - case 'replace': - _array[data.index] = data.value; - } - }; - partialSort(0, this.length - 1, 0); -}; - -/** - * Sorts the list. - * @param [callback = function(item){return(item);}] {function} The function invoked in order to get the value for the evaluation of the sort criteria. - * @example - * callback = function(item) {return -item.key;} - * This function callback will return the opposite of the attribute key of the item. In this case the list will be sorted in descending order. - * @return {void} - */ -DoubleLinkedList.prototype.sort = function (callback) { - - if (!callback) - callback = function (item) { - return item; - }; - - var outerThis = this; - - function partialSort(from, to, fromNode, toNode) { - if (from < to) { - var m = Math.floor((from + to) / 2); - var mNode = outerThis.getNode(m - from, fromNode); - partialSort(from, m, fromNode, mNode); - partialSort(m + 1, to, mNode.next, toNode); - merge(from, m, to, fromNode); - } - } - - function merge(from, m, to, fromNode) { - var left = []; - var right = []; - var node = fromNode; - for (var i = 0; i < m - from + 1; i++, node = node.next) - left[i] = node.item; - for (var j = 0; j < to - m; j++, node = node.next) - right[j] = node.item; - var x = 0, y = 0; - for (var k = from; k < to + 1; k++, fromNode = fromNode.next) { - if (y > to - m - 1 || (callback(left[x]) <= callback(right[y]) && x < m - from + 1)) { - fromNode.item = left[x]; - x++; - } else { - fromNode.item = right[y]; - y++; - } - } - } - - partialSort(0, this.length - 1, this.first, this.last); -}; - -/** - * Transforms the list into an array. - * @return {Array<*>} The array built. - */ -DoubleLinkedList.prototype.toArray = function () { - var array = []; - for (var node = this.first, i = 0; node; node = node.next, i++) - array[i] = node.item; - return array; -}; - -/** - * Returns the length of the list. - * @return {Number} The length of the list. - */ -DoubleLinkedList.prototype.getLength = function () { - return this.length; -}; - -/** - * Builds the list from the array. - * @param array {Array<*>} The array from which build the list. - * @return {void} - */ -DoubleLinkedList.prototype.fromArray = function (array) { - var node = this.first; - for (var i = 0; i < Math.min(this.length, array.length); i++, node = node.next) - node.item = array[i]; - if (this.length < array.length) - for (var j = this.length; j < array.length; j++) - this.pushBack(array[j]); - else - for (var k = array.length; k < this.length;) - this.popBack(); -}; - -/** - * Returns the items that satisfy the condition determined by the callback. - * @param callback {function} The function that implements the condition. - * @return {Array} The array that contains the items that satisfy the condition. - */ -DoubleLinkedList.prototype.filter = function (callback) { - var result = []; - for (var node = this.first; node; node = node.next) { - if (callback(node.item)) - result.push(node.item); - } - return result; -}; - -/** - * Reverses the list. This method reverses only the items, not the nodes. - * @return {void} - */ -DoubleLinkedList.prototype.reverse = function () { - for (var start = this.first, end = this.last; start !== end && start.previous !== end; start = start.next, end = end.previous) { - var item = start.item; - start.item = end.item; - end.item = item; - } -}; - -/** - * Checks if the list is empty. - * @return {boolean} True if the list is empty, false otherwise. - */ -DoubleLinkedList.prototype.isEmpty = function () { - return !this.length; -}; - -/** - * Returns the first position of the item in the list. - * @param item {*} The item to search. - * @param [callback = function(item){return(it===item);}] The condition to satisfy. The callback must accept the current item to check. - * @return {number} The first position of the item. - */ -DoubleLinkedList.prototype.indexOf = function (item, callback) { - callback = callback || function (it) { - return it === item; - }; - var i = 0; - var node = this.first; - while (node) { - if (callback(node.item)) - return i; - i++; - node = node.next; - } - return -1; -}; - -/** - * Returns the last position of the item in the list. - * @param item {*} The item to search. - * @param [callback = function(item){return(it===item);}] The condition to satisfy. The callback must accept the current item to check. - * @return {number} The last position of the item. - */ -DoubleLinkedList.prototype.lastIndexOf = function (item, callback) { - callback = callback || function (it) { - return it === item; - }; - var i = this.length - 1; - var node = this.last; - while (node) { - if (callback(node.item)) - return i; - i--; - node = node.previous; - } - return -1; -}; - -/** - * Returns all the position in which the item has been found in the list. - * @param item {*} The item to search. - * @param [callback = function(item){return(it===item);}] The condition to satisfy. The callback must accept the current item to check. - * @return {Array} The positions in which the item has been found. - */ -DoubleLinkedList.prototype.allIndexesOf = function (item, callback) { - callback = callback || function (it) { - return it === item; - }; - var i = 0; - var node = this.first; - var indexes = []; - while (node) { - if (callback(node.item)) - indexes.push(i); - i++; - node = node.next; - } - return indexes; -}; - -/** - * Adds the list at the end of this list. - * @param list {DoubleLinkedList} The list to join. - * @return {void} - */ -DoubleLinkedList.prototype.join = function (list) { - if (this.last) - this.last.next = list.first; - else - this.first = list.first; - if (list.first) - list.first.previous = this.last; - this.last = list.last; - this.length += list.length; -}; - -/** - * Divides the list at the index position. The node at the index position is the first new node of the list. - * @param index {number} The position where to divide the list. - * @return {DoubleLinkedList} The list formed by the nodes from the index position then. If the index is out of bound, the list will be empty. - */ -DoubleLinkedList.prototype.divide = function (index) { - var list = new DoubleLinkedList(); - if (index > -1 && index < this.length) { - var node = this.first; - var previous = null; - for (var i = 0; i < index; i++) { - previous = node; - node = node.next; - } - if (node === this.first) { - list.first = this.first; - list.last = this.last; - this.first = null; - this.last = null; - } else { - list.first = node; - list.last = this.last; - this.last = previous; - previous.next = null; - node.previous = null; - } - list.length = this.length - index; - this.length = index; - } - return list; -}; - -/** - * Clones the list into a new list. - * @return {DoubleLinkedList} The list cloned from this list. - */ -DoubleLinkedList.prototype.clone = function () { - var list = new DoubleLinkedList(); - var node = this.first; - for (var i = 0; i < this.length; i++, node = node.next) - if (node.item.clone) - list.pushBack(node.item.clone()); - else - list.pushBack(node.item); - return list; -}; - -/** - * Clones the list into a new list without cloning duplicated items. - * @return {DoubleLinkedList} The list cloned from this list. - */ -DoubleLinkedList.prototype.cloneDistinct = function () { - var list = new DoubleLinkedList(); - var node = this.first; - for (var i = 0; i < this.length; i++, node = node.next) - if (!list.contains(node.item)) - if (node.item.cloneDistinct) - list.pushBack(node.item.cloneDistinct()); - else if (node.item.clone) - list.pushBack(node.item.clone()); - else - list.pushBack(node.item); - return list; -}; - -/** - * Splits the list into lists of desired size. - * @param size {number} The size of the lists. - * @return {Array} The lists created by splitting the list. - */ -DoubleLinkedList.prototype.split = function (size) { - var length = this.length; - var lists = [this]; - for (var i = size; i < length; i += size) - lists.push(lists[lists.length - 1].divide(size)); - return lists; -}; - -/** - * Returns the number of items that satisfy the represented by the callback function. - * @param callback {function} The condition to satisfy. - * @return {number} The number of items that satisfy the condition. - */ -DoubleLinkedList.prototype.count = function (callback) { - var count = 0; - var node = this.first; - while (node) { - if (callback(node.item)) - count++; - node = node.next; - } - return count; -}; - -/** - * Class that implements the iterator for a double linked list. - * @param aggregate {DoubleLinkedList} The aggregate to scan. - * @constructor - */ -function DoubleLinkedListIterator(aggregate) { - /** - * The aggregate relates to this iterator. - * @type {DoubleLinkedList} - */ - this.aggregate = aggregate; - - /** - * The pointer to the position. - * @type {Node|null} - */ - this.pointer = null; -} - -/** - * Moves the iterator to the first position of the aggregate. - * @return {void} - */ -DoubleLinkedListIterator.prototype.first = function () { - this.pointer = this.aggregate.first; -}; - -/** - * Moves the iterator to the next item. - * @return {void} - */ -DoubleLinkedListIterator.prototype.next = function () { - this.pointer = this.pointer.next; -}; - -/** - * Moves the iterator to the last position of the aggregate. - * @return {void} - */ -DoubleLinkedListIterator.prototype.last = function () { - this.pointer = this.aggregate.last; -}; - -/** - * Moves the iterator to the previous item. - * @return {void} - */ -DoubleLinkedListIterator.prototype.previous = function () { - this.pointer = this.pointer.previous; -}; - -/** - * Checks if the iterator is out of the bounds of the aggregate. - * @return {boolean} It return true if the iterator is out of the bounds of the aggregate, otherwise false. - */ -DoubleLinkedListIterator.prototype.isDone = function () { - return !this.pointer; -}; - -/** - * Returns the item stored at the position pointed by the iterator. - * @abstract - * @return {*} The item stored or undefined if it's out of the bounds. - */ -DoubleLinkedListIterator.prototype.getItem = function () { - return this.pointer.item; -}; - -/** - * Returns the node stored at the position pointed by the iterator. - * @abstract - * @return {DLLNode|null} The node stored or null if it's out of the bounds. - */ -DoubleLinkedListIterator.prototype.getNode = function () { - return this.pointer; -}; - -/** - * Class for managing an hash table. - * @param size {number} The size of the table. - * @constructor - */ -function HashTable(size) { - /** - * The size of the table - * @type {number} - */ - this.size = size; - - this.p = 1000; - - this.a = Math.floor(Math.random() * this.p); - - this.b = Math.floor(Math.random() * this.p); - - /** - * Calculate the hash of the param key. - * @param key {number} The key to hash. - * @return {number} The hash of the key. - */ - this.hash = function (key) { - return ((this.a * key + this.b) % this.p) % this.size; - }; - - /** - * The items stored in the hash table. - * @type {Array} - */ - this.items = []; - - /** - * The number of keys stored in the hash table. - * @type {number} - */ - this.keyLength = 0; - - this.clear(); -} - -/** - * Stores the item with its key. - * @param key {number} The key relatives to the item. - * @param item {*} The item to store. - */ -HashTable.prototype.insert = function (key, item) { - this.keyLength++; - this.items[this.hash(key)].pushBack({key: key, item: item}); -}; - -/** - * Deletes the first item relatives to the key value. - * @param key {number} The key to delete. - * @return {void} - */ -HashTable.prototype.deleteKey = function (key) { - var list = this.items[this.hash(key)]; - var it = list.getIterator(); - for (it.first(); !it.isDone() && it.getItem().key !== key;) - it.next(); - if (!it.isDone()) { - list.deleteNode(it.getNode()); - this.keyLength--; - } -}; - -/** - * Deletes all the items relative to the key value. - * @param key {number} The key to delete. - * @return {void} - */ -HashTable.prototype.deleteAllKey = function (key) { - var list = this.items[this.hash(key)]; - var it = list.getIterator(); - var keysRemoved = 0; - for (it.first(); !it.isDone(); it.next()) - if (it.getItem().key === key) { - list.deleteNode(it.getNode()); - keysRemoved++; - } - this.keyLength -= keysRemoved; -}; - -/** - * Searches the item relative to the key value. - * @param key {number} The key of the item to search. - * @return {*|undefined} The item found or undefined if the key does not exist. - */ -HashTable.prototype.search = function (key) { - var list = this.items[this.hash(key)]; - var it = list.getIterator(); - for (it.first(); !it.isDone(); it.next()) - if (it.getItem().key === key) - return it.getItem().item; - return undefined; -}; - -/** - * Checks if the hash table contains a key that satisfy the condition represented by the callback function. - * @param key {number} The key to find. - * @param [callback = function(k){return(k===key);}] The condition to satisfy. The callback must accept the current key to check. - * @return {boolean} True if the hash table contains the key that satisfy the condition, false otherwise. - */ -HashTable.prototype.containsKey = function (key, callback) { - callback = callback || function (k) { - return k === key; - }; - var list = this.items[this.hash(key)]; - var it = list.getIterator(); - for (it.first(); !it.isDone(); it.next()) - if (callback(it.getItem().key)) - return true; - return false; -}; - -/** - * Searches all the items relative to the key value. - * @param key {number} The key of the items to search. - * @return {Array.<*>} An array with the items found. - */ -HashTable.prototype.searchAll = function (key) { - var list = this.items[this.hash(key)]; - var it = list.getIterator(); - var array = []; - for (it.first(); !it.isDone(); it.next()) - if (it.getItem().key === key) - array.push(it.getItem().item); - return array; -}; - -/** - * Returns the keys stored in the hash table. - * @return {Array} The keys stored in the table. - */ -HashTable.prototype.getKeys = function () { - var keys = []; - for (var i = 0; i < this.size; i++) { - var it = this.items[i].getIterator(); - for (it.first(); !it.isDone(); it.next()) - keys.push(it.getItem().key); - } - return keys; -}; - -/** - * Returns the items stored in the hash table. - * @return {Array<*>} The items stored in the table. - */ -HashTable.prototype.getItems = function () { - var items = []; - for (var i = 0; i < this.size; i++) { - var it = this.items[i].getIterator(); - for (it.first(); !it.isDone(); it.next()) - items.push(it.getItem().item); - } - return items; -}; - -/** - * Removes all the keys and the items stored in the hash table. - * @return {void} - */ -HashTable.prototype.clear = function () { - this.items = []; - for (var i = 0; i < this.size; i++) - this.items[i] = new DoubleLinkedList(); - this.keyLength = 0; -}; - -/** - * Returns the number of keys stored in the hash table. - * @return {number} The number of keys stored. - */ -HashTable.prototype.getNumberOfKeys = function () { - return this.keyLength; -}; - -/** - * Checks if the hash table is empty. - * @return {boolean} True if the hash table is empty, false otherwise. - */ -HashTable.prototype.isEmpty = function () { - return !this.keyLength; -}; - -/** - * Executes the callback function for each item of the hash table. - * This method modifies the hash table so if you don't need to modify it you must return the same item stored. - * @param callback {function} The function to execute for each item. The function must accept the current item on which execute the function. - * @return {void} - */ -HashTable.prototype.execute = function (callback) { - for (var i = 0; i < this.size; i++) - this.items[i].execute(callback); -}; - -/** - * Returns the items that satisfy the condition determined by the callback. - * @param callback {function} The function that implements the condition. - * @return {Array<*>} The array that contains the items that satisfy the condition. - */ -HashTable.prototype.filter = function (callback) { - var result = []; - for (var i = 0; i < this.size; i++) - result.concat(this.items[i].filter(callback)); - return result; -}; - -/** - * Returns the size of the hash table. - * @return {number} The size of the hash table. - */ -HashTable.prototype.getSize = function () { - return this.size; -}; - -/** - * Clones the hash table into a new hash table. - * @return {HashTable} The hash table cloned from this hash table. - */ -HashTable.prototype.clone = function () { - var table = new HashTable(this.size); - for (var i = 0; i < this.size; i++) - for (var node = this.items[i].first; node; node = node.next) - table.insert(node.key, node.item); - return table; -}; - -/** - * Class for managing a linked list. - * @param {...*} [args] The items for initializing the list. - * @constructor - */ -function LinkedList(args) { - /** - * The first node of the list. - * @type {LLNode|null} - */ - this.first = null; - /** - * The last node of the list. - * @type {LLNode|null} - */ - this.last = null; - /** - * The length of the list. - * @type {number} - */ - this.length = 0; - //builds the list from the parameters of the constructor - this.fromArray(arguments); -} - -/** - * Returns the iterator relative to the aggregate. - * @return {Iterator} The iterator. - */ -LinkedList.prototype.getIterator = function () { - return new LinkedListIterator(this); -}; - -/** - * Adds an item at the head of the list. - * @param item {*} The item to add. - * @return {void} - */ -LinkedList.prototype.pushFront = function (item) { - var node = new LLNode(item); - node.next = this.first; - this.first = node; - if (!this.last) - this.last = node; - this.length++; -}; - -/** - * Adds an item at the tail of the list. - * @param item {*} The item to add. - * @return {void} - */ -LinkedList.prototype.pushBack = function (item) { - var node = new LLNode(item); - if (this.last) - this.last.next = node; - else - this.first = node; - this.last = node; - this.length++; -}; - -/** - * Removes the first item of the list. - * @return {*} The item removed. It's undefined if the list is empty. - */ -LinkedList.prototype.popFront = function () { - if (this.length) { - var node = this.first; - this.first = this.first.next; - this.length--; - node.next = null; - return node.item; - } - return undefined; -}; - -/** - * Removes the last item of the list. - * @return {*} The item removed. It's undefined if the list is empty. - */ -LinkedList.prototype.popBack = function () { - if (this.length) { - var node = this.last; - var next = this.first; - while (next.next && next.next.next) { - next = next.next; - } - if (node === next) - this.last = null; - else - this.last = next; - next.next = null; - this.length--; - return node.item; - } - return undefined; -}; - -/** - * Removes the first times items of the list. - * @param times {number} The number of times to repeat the popFront method. - * @return {*} The item removed. It's undefined if the list is empty. - */ -LinkedList.prototype.multiPopFront = function (times) { - var result = []; - for (var i = 0; i < times && this.length; i++) - result.push(this.popFront()); - return result; -}; - -/** - * Removes the last times items of the list. - * @param times {number} The number of times to repeat the popBack method. - * @return {*} The items removed. - */ -LinkedList.prototype.multiPopBack = function (times) { - var result = []; - for (var i = 0; i < times && this.length; i++) - result.push(this.popBack()); - return result; -}; - -/** - * Returns the first item of the list without remove it. - * @return {*} The item at the top of the list. It's undefined if the list is empty. - */ -LinkedList.prototype.peek = function () { - if (!this.length) - return undefined; - return this.first.item; -}; - -/** - * Adds the item at the index position. - * @param item {*} The item to add. - * @param index {number} The position where to add the item. If index is negative, the item won't be added. - * @return {void} - */ -LinkedList.prototype.addAt = function (item, index) { - if (index < 0) - return; - if (!index) { - this.pushFront(item); - return; - } - if (index === this.length) { - this.pushBack(item); - return; - } - var node = this.first; - if (!node && index > 0) - this.pushBack(undefined); - for (var i = 0; i < index - 1; i++, node = node.next) { - if (node === this.last) - this.pushBack(undefined); - } - if (node === this.last) - this.pushBack(item); - else if (node === this.first) - this.pushFront(item); - else { - var newNode = new LLNode(item); - newNode.next = node.next; - node.next = newNode; - this.length++; - } -}; - -/** - * Removes the item at the index position. - * @param index {number} The position of the item to remove. - * @return {*} The item stored at the position index. It's undefined if the index is out of bounds. - */ -LinkedList.prototype.removeAt = function (index) { - if (index < 0 || index > this.length - 1) - return undefined; - if (index === 0) - return this.popFront(); - if (index === this.length - 1) - return this.popBack(); - var node = this.first; - for (; index > 1; index--) - node = node.next; - //now node is the node before the node to remove - //node to remove - var next = node.next; - node.next = next.next; - this.length--; - return next.item; -}; - -/** - * Removes the item from the list. - * @param item {*} The item to remove. - * @param [callback = function(item){return(it===item);}] The condition to satisfy. The callback must accept the current item to check. - * @return {void} - */ -LinkedList.prototype.remove = function (item, callback) { - callback = callback || function (it) { - return it === item; - }; - var node = this.first; - var previous = null; - while (node) { - if (callback(node.item)) { - if (node === this.first) - this.first = node.next; - if (node === this.last) - this.last = previous; - if (previous) - previous.next = node.next; - return; - } - previous = node; - node = node.next; - } -}; - -/** - * Removes all the item from the list. - * @param item {*} The item to remove. - * @param [callback = function(item){return(it===item);}] The condition to satisfy. The callback must accept the current item to check. - * @return {void} - */ -LinkedList.prototype.removeAll = function (item, callback) { - callback = callback || function (it) { - return it === item; - }; - var node = this.first; - var previous = null; - while (node) { - if (callback(node.item)) { - if (node === this.first) - this.first = node.next; - if (node === this.last) - this.last = previous; - if (previous) - previous.next = node.next; - } else - previous = node; - node = node.next; - } -}; - -/** - * Removes all the items stored from the from position to the to position. - * If from > to, the method will remove all the items up to the end. - * @param from {number} The position where start to remove the items. The from position is included. - * @param to {number} The position where stop to remove the items. The to position is included. - * @return {Array<*>} The items removed. - */ -LinkedList.prototype.removeSegment = function (from, to) { - var result = []; - if (to > -1 && from < this.length) { - if (from === 0) - return this.multiPopFront(to + 1); - if (to === this.length - 1 || from > to) - return this.multiPopBack(Math.max(to - from, this.length - from)).reverse(); - var node = this.first; - for (var i = 0; i < from - 1; i++) - node = node.next; - //now node is the node before the node to remove - //node to remove - var next = node.next; - for (var j = from; j < to + 1 && j < this.length; j++) { - result.push(next.item); - next = next.next; - } - this.length -= Math.min(to - from + 1, this.length - from); - node.next = next; - } - return result; -}; - -/** - * Changes the item stored in the index position. If the index is out of bound, the node won't be updated. - * @param index {number} The position of the node to modify. - * @param item {*} The new item stored in the node. - * @return {void} - */ -LinkedList.prototype.modifyAt = function (index, item) { - var node = this.getNode(index); - if (node) - node.item = item; -}; - -/** - * Removes all the items stored in the list. - * @return {void} - */ -LinkedList.prototype.clear = function () { - this.first = null; - this.last = null; - this.length = 0; -}; - -/** - * Checks if the list contains an item that satisfy the condition represented by the callback function. - * @param item {*} The item to find. - * @param [callback = function(item){return(it===item);}] The condition to satisfy. The callback must accept the current item to check. - * @return {boolean} True if the list contains the item that satisfy the condition, false otherwise. - */ -LinkedList.prototype.contains = function (item, callback) { - callback = callback || function (it) { - return it === item; - }; - var i = 0; - var node = this.first; - while (i < this.length && !callback(node.item)) { - i++; - node = node.next; - } - return i < this.length; -}; - -/** - * Executes the callback function for each item of the stack. - * This method modifies the list so if you don't need to modify it you must return the same item of the array. - * @param callback {function} The function to execute for each item. The function must accept the current item on which execute the function. - * @return {void} - */ -LinkedList.prototype.execute = function (callback) { - var node = this.first; - while (node) { - node.item = callback(node.item); - node = node.next; - } -}; - -/** - * Returns the node at the position index. - * @param index {number} The position of the node. - * @return {LLNode} The node stored at the position index. It's undefined if index isn't in the list bounds. - */ -LinkedList.prototype.getNode = function (index) { - if (index < 0 || index > this.length - 1) - return undefined; - var node = this.first; - for (; index > 0; index--) - node = node.next; - return node; -}; - -/** - * Returns the item at the position index. - * @param index {number} The position of the item. - * @return {*} The item stored at the position index. It's undefined if index isn't in the list bounds. - */ -LinkedList.prototype.getItem = function (index) { - if (index < 0 || index > this.length - 1) - return undefined; - var node = this.first; - for (; index > 0; index--) - node = node.next; - return node.item; -}; - -/** - * Transforms the list into an array. - * @return {Array<*>} The array built. - */ -LinkedList.prototype.toArray = function () { - var array = []; - for (var node = this.first, i = 0; node; node = node.next, i++) - array[i] = node.item; - return array; -}; - -/** - * Returns the length of the list. - * @return {Number} The length of the list. - */ -LinkedList.prototype.getLength = function () { - return this.length; -}; - -/** - * Builds the list from the array. - * @param array {Array<*>} The array from which build the list. - * @return {void} - */ -LinkedList.prototype.fromArray = function (array) { - var node = this.first; - for (var i = 0; i < Math.min(this.length, array.length); i++, node = node.next) - node.item = array[i]; - if (this.length < array.length) - for (var j = this.length; j < array.length; j++) - this.pushBack(array[j]); - else - for (var k = array.length; k < this.length;) - this.popBack(); -}; - -/** - * Returns the items that satisfy the condition determined by the callback. - * @param callback {function} The function that implements the condition. - * @return {Array<*>} The array that contains the items that satisfy the condition. - */ -LinkedList.prototype.filter = function (callback) { - var result = []; - for (var node = this.first; node; node = node.next) { - if (callback(node.item)) - result.push(node.item); - } - return result; -}; - -/** - * Checks if the list is empty. - * @return {boolean} True if the list is empty, false otherwise. - */ -LinkedList.prototype.isEmpty = function () { - return !this.length; -}; - -/** - * Returns the first position of the item in the list. - * @param item {*} The item to search. - * @param [callback = function(item){return(it===item);}] The condition to satisfy. The callback must accept the current item to check. - * @return {number} The first position of the item. - */ -LinkedList.prototype.indexOf = function (item, callback) { - callback = callback || function (it) { - return it === item; - }; - var i = 0; - var node = this.first; - while (node) { - if (callback(node.item)) - return i; - i++; - node = node.next; - } - return -1; -}; - -/** - * Returns the last position of the item in the list. - * @param item {*} The item to search. - * @param [callback = function(item){return(it===item);}] The condition to satisfy. The callback must accept the current item to check. - * @return {number} The last position of the item. - */ -LinkedList.prototype.lastIndexOf = function (item, callback) { - callback = callback || function (it) { - return it === item; - }; - var i = 0; - var node = this.first; - var index = -1; - while (node) { - if (callback(node.item)) - index = i; - i++; - node = node.next; - } - return index; -}; - -/** - * Returns all the position in which the item has been found in the list. - * @param item {*} The item to search. - * @param [callback = function(item){return(it===item);}] The condition to satisfy. The callback must accept the current item to check. - * @return {Array} The positions in which the item has been found. - */ -LinkedList.prototype.allIndexesOf = function (item, callback) { - callback = callback || function (it) { - return it === item; - }; - var i = 0; - var node = this.first; - var indexes = []; - while (node) { - if (callback(node.item)) - indexes.push(i); - i++; - node = node.next; - } - return indexes; -}; - -/** - * Joins the list at the end of this list. - * @param list {LinkedList} The list to join. - * @return {void} - */ -LinkedList.prototype.join = function (list) { - if (this.last) - this.last.next = list.first; - else - this.first = list.first; - this.last = list.last; - this.length += list.length; -}; - -/** - * Divides the list at the index position. The node at the index position is the first new node of the list. - * @param index {number} The position where to divide the list. - * @return {LinkedList} The list formed by the nodes from the index position then. If the index is out of bound, the list will be empty. - */ -LinkedList.prototype.divide = function (index) { - var list = new LinkedList(); - if (index > -1 && index < this.length) { - var node = this.first; - var previous = null; - for (var i = 0; i < index; i++) { - previous = node; - node = node.next; - } - if (node === this.first) { - list.first = this.first; - list.last = this.last; - this.first = null; - this.last = null; - } else { - list.first = node; - list.last = this.last; - this.last = previous; - previous.next = null; - } - list.length = this.length - index; - this.length = index; - } - return list; -}; - -/** - * Clones the list into a new list. - * @return {LinkedList} The list cloned from this list. - */ -LinkedList.prototype.clone = function () { - var list = new LinkedList(); - var node = this.first; - for (var i = 0; i < this.length; i++, node = node.next) - if (node.item.clone) - list.pushBack(node.item.clone()); - else - list.pushBack(node.item); - return list; -}; - -/** - * Clones the list into a new list without cloning duplicated items. - * @return {LinkedList} The list cloned from this list. - */ -LinkedList.prototype.cloneDistinct = function () { - var list = new LinkedList(); - var node = this.first; - for (var i = 0; i < this.length; i++, node = node.next) - if (!list.contains(node.item)) - if (node.item.cloneDistinct) - list.pushBack(node.item.cloneDistinct()); - else if (node.item.clone) - list.pushBack(node.item.clone()); - else - list.pushBack(node.item); - return list; -}; - -/** - * Splits the list into lists of desired size. - * @param size {number} The size of the lists. - * @return {Array} The lists created by splitting the list. - */ -LinkedList.prototype.split = function (size) { - var length = this.length; - var lists = [this]; - for (var i = size; i < length; i += size) - lists.push(lists[lists.length - 1].divide(size)); - return lists; -}; - -/** - * Returns the number of items that satisfy the represented by the callback function. - * @param callback {function} The condition to satisfy. - * @return {number} The number of items that satisfy the condition. - */ -LinkedList.prototype.count = function (callback) { - var count = 0; - var node = this.first; - while (node) { - if (callback(node.item)) - count++; - node = node.next; - } - return count; -}; - -/** - * Class that implements the iterator for a linked list. - * @param aggregate {LinkedList} The aggregate to scan. - * @constructor - */ -function LinkedListIterator(aggregate) { - /** - * The aggregate relates to this iterator. - * @type {LinkedList} - */ - this.aggregate = aggregate; - - /** - * The pointer to the position. - * @type {Node|null} - */ - this.pointer = null; -} - -/** - * Moves the iterator to the first position of the aggregate. - * @return {void} - */ -LinkedListIterator.prototype.first = function () { - this.pointer = this.aggregate.first; -}; - -/** - * Moves the iterator to the next item. - * @return {void} - */ -LinkedListIterator.prototype.next = function () { - this.pointer = this.pointer.next; -}; - -/** - * Moves the iterator to the last position of the aggregate. - * @return {void} - */ -LinkedListIterator.prototype.last = function () { - this.pointer = this.aggregate.last; -}; - -/** - * Moves the iterator to the previous item. - * @return {void} - */ -LinkedListIterator.prototype.previous = function () { - var node = this.pointer; - for (this.pointer = this.first(); this.pointer.next !== node;) - this.next(); -}; - -/** - * Checks if the iterator is out of the bounds of the aggregate. - * @return {boolean} It return true if the iterator is out of the bounds of the aggregate, otherwise false. - */ -LinkedListIterator.prototype.isDone = function () { - return !this.pointer; -}; - -/** - * Returns the item stored at the position pointed by the iterator. - * @return {*} The item stored or undefined if it's out of the bounds. - */ -LinkedListIterator.prototype.getItem = function () { - return this.pointer.item; -}; - -/** - * Returns the node stored at the position pointed by the iterator. - * @abstract - * @return {Node|null} The node stored or null if it's out of the bounds. - */ -LinkedListIterator.prototype.getNode = function () { - return this.pointer; -}; - -/** - * Class for managing a priority queue. - * @constructor - */ -function PriorityQueue() { - /** - * The list of the items in the queue. - * @type {RBTreeList} - */ - this.items = new RBTreeList(); - /** - * The length of the queue. - * @type {number} - */ - this.length = 0; -} - -/** - * Returns the iterator relative to the aggregate. - * @return {Iterator} The iterator. - */ -PriorityQueue.prototype.getIterator = function () { - return new PriorityQueueIterator(this); -}; - -/** - * Adds the item at the tail of the queue. - * @param priority {number} The priority of the item. - * @param item {*} The item to add. - * @return {void} - */ -PriorityQueue.prototype.enqueue = function (priority, item) { - var queue = this.items.search(priority); - if (!queue) { - queue = new Queue(); - this.items.insert(priority, queue); - } - queue.enqueue(item); - this.length++; -}; - -/** - * Adds the items with the same priority at the tail of the queue. - * @param priority {number} The priority of the items. - * @param items {Array<*>} The items to add. - * @return {void} - */ -PriorityQueue.prototype.multiEnqueue = function (priority, items) { - for (var i = 0; i < items.length; i++) - this.enqueue(priority, items[i]); -}; - -/** - * Removes the item at the head of the queue. - * @return {*} The item at the head of the queue. It's undefined if the queue is empty. - */ -PriorityQueue.prototype.dequeue = function () { - var node = this.items.maximum(); - var item = undefined; - if (node) { - var queue = node.item; - item = queue.dequeue(); - if (queue.isEmpty()) - this.items.deleteNode(node); - this.length--; - } - return item; -}; - -/** - * Removes the items at the head of the queue. - * @param times {number} The number of times to repeat the dequeue method. - * @return {Array<*>} The items at the head of the queue. - */ -PriorityQueue.prototype.multiDequeue = function (times) { - var items = []; - for (var i = 0; i < times && this.length; i++) - items.push(this.dequeue()); - return items; -}; - -/** - * Removes the first length items from the position index. - * @param index {number} The position where to start to remove the items. - * @param [length = 1] {number} The number of items to remove. - * @return {void} - */ -PriorityQueue.prototype.remove = function (index, length) { - length = length || 1; - var it = this.items.getIterator(); - for (it.last(); !it.isDone() && length > 0; it.previous()) { - var queue = it.getItem(); - if (index > -1 && index < queue.getLength()) { - var oldLength = queue.getLength(); - queue.remove(index, length); - length -= oldLength - index; - index = 0; - if (!queue.getLength()) - this.items.deleteNode(it.getNode()); - } else - index = index - queue.getLength(); - } -}; - -/** - * Returns the item at the position index. - * @param index {number} The index of the item. - * @return {*} The item found. It's undefined if the position index is out of bounds. - */ -PriorityQueue.prototype.getItem = function (index) { - var it = this.items.getIterator(); - for (it.last(); !it.isDone(); it.previous()) { - var queue = it.getItem(); - if (index > -1 && index < queue.getLength()) - return queue.getItem(index); - index = index - queue.getLength(); - } - return undefined; -}; - -/** - * Returns the items relatives to the priority. - * @param priority {number} The priority of the items. - * @return {Array<*>} The items found. - */ -PriorityQueue.prototype.getItems = function (priority) { - var items = this.items.search(priority); - if (items) - return items.items; - return []; -}; - -/** - * Returns the first item in the queue. The item is not removed. - * @return {*} The first item. It's undefined if the queue is empty. - */ -PriorityQueue.prototype.peek = function () { - return this.items.maximum().item.peek(); -}; - -/** - * Returns the length of the queue. - * @return {number} The length of the queue. - */ -PriorityQueue.prototype.getLength = function () { - return this.length; -}; - -/** - * Checks if the queue is empty. - * @return {boolean} True if the queue is empty, false otherwise. - */ -PriorityQueue.prototype.isEmpty = function () { - return !this.length; -}; - -/** - * Removes all the items stored in the queue. - * @return {void} - */ -PriorityQueue.prototype.clear = function () { - this.items = new RBTreeList(); - this.length = 0; -}; - -/** - * Checks if the queue contains a priority that satisfy the condition represented by the callback function. - * @param priority {number} The priority to find. - * @param [callback = function(p){return(p===priority);}] The condition to satisfy. The callback must accept the current priority to check. - * @return {boolean} True if the queue contains the priority that satisfy the condition, false otherwise. - */ -PriorityQueue.prototype.containsPriority = function (priority, callback) { - if (callback) - return this.items.fullContains(callback); - else - return this.items.contains(priority); -}; - -/** - * Returns the queue created by the priority queue with the items in the same order but without the priority. - * @return {Queue} The queue created. - */ -PriorityQueue.prototype.toQueue = function () { - var queue = new Queue(); - var it = this.items.getIterator(); - for (it.last(); !it.isDone(); it.previous()) { - var item = it.getItem(); - var itQ = item.getIterator(); - for (itQ.first(); !itQ.isDone(); itQ.next()) - queue.enqueue(itQ.getItem()); - } - return queue; -}; - -/** - * Executes the callback function for each item of the queue. - * This method modifies the queue so if you don't need to modify it you must return the same item of the array. - * @param callback {function} The function to execute for each item. The function must accept the current item on which execute the function. - * @return {void} - */ -PriorityQueue.prototype.execute = function (callback) { - var it = this.items.getIterator(); - for (it.last(); !it.isDone(); it.previous()) - it.getItem().execute(callback); -}; - -/** - * Changes the priority of the item at the position index. - * @param index {number} The position of the item of which increase the priority. - * @param newPriority {number} The new priority. - * @return {void} - */ -PriorityQueue.prototype.changePriority = function (index, newPriority) { - var item = this.getItem(index); - this.remove(index); - this.enqueue(newPriority, item); -}; - -/** - * Returns the items that satisfy the condition determined by the callback. - * @param callback {function} The function that implements the condition. - * @return {Array<*>} The array that contains the items that satisfy the condition. - */ -PriorityQueue.prototype.filter = function (callback) { - var result = []; - var it = this.items.getIterator(); - for (it.last(); !it.isDone(); it.previous()) { - var itQ = it.getItem().getIterator(); - for (itQ.first(); !itQ.isDone(); itQ.next()) { - if (callback(itQ.getItem())) - result.push(itQ.getItem()); - } - } - return result; -}; - -/** - * Clones the queue into a new queue. - * @return {PriorityQueue} The queue cloned from this queue. - */ -PriorityQueue.prototype.clone = function () { - var queue = new PriorityQueue(); - queue.items = this.items.clone(); - queue.length = this.length; - return queue; -}; - -/** - * Clones the queue into a new queue without cloning duplicated items. - * @return {PriorityQueue} The queue cloned from this queue. - */ -PriorityQueue.prototype.cloneDistinct = function () { - var queue = new PriorityQueue(); - queue.items = this.items.cloneDistinct(); - queue.length = queue.items.getSize(); - return queue; -}; - -/** - * Class that implements the iterator for a priority queue. - * @param aggregate {PriorityQueue} The aggregate to scan. - * @constructor - */ -function PriorityQueueIterator(aggregate) { - /** - * The aggregate relates to this iterator. - * @type {PriorityQueue} - */ - this.aggregate = aggregate; - - /** - * The pointer to the position of the node. - * @type {RBLNode|null} - */ - this.pointerNode = null; - /** - * The pointer to the position in the node. - * @type {number} - */ - this.pointerPosition = -1; -} - -/** - * Moves the iterator to the first position of the aggregate. - * @return {void} - */ -PriorityQueueIterator.prototype.first = function () { - this.pointerNode = this.aggregate.items.maximum(); - this.pointerPosition = 0; -}; - -/** - * Moves the iterator to the next item. - * @return {void} - */ -PriorityQueueIterator.prototype.next = function () { - this.pointerPosition++; - if (this.pointerPosition > this.pointerNode.item.getLength() - 1) { - this.pointerNode = this.pointerNode.previous; - this.pointerPosition = 0; - } -}; - -/** - * Moves the iterator to the last position of the aggregate. - * @return {void} - */ -PriorityQueueIterator.prototype.last = function () { - this.pointerNode = this.aggregate.items.minimum(); - this.pointerPosition = this.pointerNode.item.getLength() - 1; -}; - -/** - * Moves the iterator to the previous item. - * @return {void} - */ -PriorityQueueIterator.prototype.previous = function () { - this.pointerPosition--; - if (this.pointerPosition < 0) { - this.pointerNode = this.pointerNode.next; - if (this.pointerNode) - this.pointerPosition = this.pointerNode.item.getLength() - 1; - } -}; - -/** - * Checks if the iterator is out of the bounds of the aggregate. - * @return {boolean} It return true if the iterator is out of the bounds of the aggregate, otherwise false. - */ -PriorityQueueIterator.prototype.isDone = function () { - return !this.pointerNode; -}; - -/** - * Returns the item stored at the position pointed by the iterator. - * @return {*} The item stored or undefined if it's out of the bounds. - */ -PriorityQueueIterator.prototype.getItem = function () { - return this.pointerNode.item.items[this.pointerPosition]; -}; - -/** - * Class for managing a queue. - * @param {...*} [args] The items for initializing the queue. - * @constructor - */ -function Queue(args) { - /** - * The list of the items in the queue. - * @type {Array<*>} - */ - this.items = []; - - //builds the queue from the parameters of the constructor - this.multiEnqueue(arguments); -} - -/** - * Returns the iterator relative to the aggregate. - * @return {Iterator} The iterator. - */ -Queue.prototype.getIterator = function () { - return new QueueIterator(this); -}; - -/** - * Adds the item at the tail of the queue. - * @param item {*} The item to add. - * @return {void} - */ -Queue.prototype.enqueue = function (item) { - this.items.push(item); -}; - -/** - * Adds the items at the tail of the queue. - * @param items {Array<*>} The items to add. - * @return {void} - */ -Queue.prototype.multiEnqueue = function (items) { - for (var i = 0; i < items.length; i++) - this.items.push(items[i]); -}; - -/** - * Removes the item at the head of the queue. - * @return {*} The item at the head of the queue. It's undefined if the queue is empty. - */ -Queue.prototype.dequeue = function () { - if (!this.items.length) - return undefined; - return this.items.splice(0, 1)[0]; //remove the first item and return it -}; - -/** - * Removes the items at the head of the queue. - * @param times {number} The number of times to repeat the dequeue method. - * @return {Array<*>} The items at the head of the queue. - */ -Queue.prototype.multiDequeue = function (times) { - return this.items.splice(0, times); //removes the last times item and returns the array -}; - -/** - * Removes the first length items from the position index. - * @param index {number} The position where to start to remove the items. - * @param [length = 1] {number} The number of items to remove. - * @return {void} - */ -Queue.prototype.remove = function (index, length) { - length = length || 1; - this.items.splice(index, length); -}; - -/** - * Returns the item at the position index. - * @param index {number} The position of the item. - * @return {*} The item at the position. It's undefined if index isn't in the queue bounds. - */ -Queue.prototype.getItem = function (index) { - if (index < 0 || index > this.items.length - 1) - return undefined; - return this.items[index]; -}; - -/** - * Returns the first item in the queue. The item is not removed. - * @return {*} The first item. It's undefined if the queue is empty. - */ -Queue.prototype.peek = function () { - if (this.items.length) - return this.items[0]; - return undefined -}; - -/** - * Removes all the items stored in the queue. - * @return {void} - */ -Queue.prototype.clear = function () { - this.items = []; -}; - -/** - * Checks if the queue contains an item that satisfy the condition represented by the callback function. - * @param item {*} The item to find. - * @param [callback = function(item){return(it===item);}] The condition to satisfy. The callback must accept the current item to check. - * @return {boolean} True if the queue contains the item that satisfy the condition, false otherwise. - */ -Queue.prototype.contains = function (item, callback) { - callback = callback || function (it) { - return it === item; - }; - var i = 0; - while (i < this.items.length && !callback(this.items[i])) - i++; - return i < this.items.length; -}; - -/** - * Executes the callback function for each item of the queue. - * This method modifies the queue so if you don't need to modify it you must return the same item of the array. - * @param callback {function} The function to execute for each item. The function must accept the current item on which execute the function. - * @return {void} - */ -Queue.prototype.execute = function (callback) { - for (var i = 0; i < this.items.length; i++) - this.items[i] = callback(this.items[i]); -}; - -/** - * Returns the length of the queue. - * @return {number} The length of the queue. - */ -Queue.prototype.getLength = function () { - return this.items.length; -}; - -/** - * Checks if the queue is empty. - * @return {boolean} True if the queue is empty, false otherwise. - */ -Queue.prototype.isEmpty = function () { - return !this.items.length; -}; - -/** - * Returns the items that satisfy the condition determined by the callback. - * @param callback {function} The function that implements the condition. - * @return {Array<*>} The array that contains the items that satisfy the condition. - */ -Queue.prototype.filter = function (callback) { - var result = []; - for (var i = 0; i < this.items.length; i++) - if (callback(this.items[i])) - result.push(this.items[i]); - return result; -}; - -/** - * Returns the first position of the item in the queue. - * @param item {*} The item to search. - * @param [callback = function(item){return(it===item);}] The condition to satisfy. The callback must accept the current item to check. - * @return {number} The first position of the item. - */ -Queue.prototype.indexOf = function (item, callback) { - callback = callback || function (it) { - return it === item; - }; - var i = 0; - while (i < this.items.length) { - if (callback(this.items[i])) - return i; - i++; - } - return -1; -}; - -/** - * Returns the last position of the item in the queue. - * @param item {*} The item to search. - * @param [callback = function(item){return(it===item);}] The condition to satisfy. The callback must accept the current item to check. - * @return {number} The last position of the item. - */ -Queue.prototype.lastIndexOf = function (item, callback) { - callback = callback || function (it) { - return it === item; - }; - var i = this.items.length - 1; - while (i > -1) { - if (callback(this.items[i])) - return i; - i--; - } - return -1; -}; - -/** - * Returns all the position in which the item has been found in the queue. - * @param item {*} The item to search. - * @param [callback = function(item){return(it===item);}] The condition to satisfy. The callback must accept the current item to check. - * @return {Array} The positions in which the item has been found. - */ -Queue.prototype.allIndexesOf = function (item, callback) { - callback = callback || function (it) { - return it === item; - }; - var i = 0; - var indexes = []; - while (i < this.items.length) { - if (callback(this.items[i])) - indexes.push(i); - i++; - } - return indexes; -}; - -/** - * Clones the queue into a new queue. - * @return {Queue} The queue cloned from this queue. - */ -Queue.prototype.clone = function () { - var queue = new Queue(); - for (var i = 0; i < this.items.length; i++) - if (this.items[i].clone) - queue.enqueue(this.items[i].clone()); - else - queue.enqueue(this.items[i]); - - return queue; -}; - -/** - * Clones the queue into a new queue without cloning duplicated items. - * @return {Queue} The queue cloned from this queue. - */ -Queue.prototype.cloneDistinct = function () { - var queue = new Queue(); - for (var i = 0; i < this.items.length; i++) - if (!queue.contains(this.items[i])) - if (this.items[i].cloneDistinct) - queue.enqueue(this.items[i].cloneDistinct()); - else if (this.items[i].clone) - queue.enqueue(this.items[i].clone()); - else - queue.enqueue(this.items[i]); - return queue; -}; - -/** - * Class that implements the iterator for a linked list. - * @param aggregate {Queue} The aggregate to scan. - * @constructor - */ -function QueueIterator(aggregate) { - /** - * The aggregate relates to this iterator. - * @type {Queue} - */ - this.aggregate = aggregate; - - /** - * The pointer to the position. - * @type {number} - */ - this.pointer = -1; -} - -/** - * Moves the iterator to the first position of the aggregate. - * @return {void} - */ -QueueIterator.prototype.first = function () { - this.pointer = 0; -}; - -/** - * Moves the iterator to the next item. - * @return {void} - */ -QueueIterator.prototype.next = function () { - this.pointer++; -}; - -/** - * Moves the iterator to the last position of the aggregate. - * @return {void} - */ -QueueIterator.prototype.last = function () { - this.pointer = this.aggregate.items.length - 1; -}; - -/** - * Moves the iterator to the previous item. - * @return {void} - */ -QueueIterator.prototype.previous = function () { - this.pointer--; -}; - -/** - * Checks if the iterator is out of the bounds of the aggregate. - * @return {boolean} It return true if the iterator is out of the bounds of the aggregate, otherwise false. - */ -QueueIterator.prototype.isDone = function () { - return this.pointer < 0 || this.pointer > this.aggregate.items.length - 1; -}; - -/** - * Returns the item stored at the position pointed by the iterator. - * @return {*} The item stored or undefined if it's out of the bounds. - */ -QueueIterator.prototype.getItem = function () { - return this.aggregate.getItem(this.pointer); -}; - -/** - * Class for managing a red-black tree. - * @constructor - */ -function RBTree() { - /** - * The root of the tree. - * @type {RBNode|null} - */ - this.root = null; - /** - * The number of items stored in the tree. - * @type {number} - */ - this.size = 0; -} - -/** - * Returns the iterator relative to the aggregate. - * @return {Iterator} The iterator. - */ -RBTree.prototype.getIterator = function () { - return new RBTreeIterator(this); -}; - -/** - * Inserts the item relatives to the key value in the tree. - * @param key {number} The key to store. - * @param item {*} The item to store. - * @return {void} - */ -RBTree.prototype.insert = function (key, item) { - var node = new RBNode(key, item); - this.size++; - if (!this.root) { - this.root = node; - node.type = 'b'; - return; - } - var p = this.root; - for (var n = this.root; n;) { - p = n; - if (key < n.key) - n = n.left; - else - n = n.right; - } - node.parent = p; - if (!p) - this.root = node; - else if (key < p.key) - p.left = node; - else - p.right = node; - - this.insertFixUp(node); -}; - -/** - * Preserves the properties of the tree after an insert. - * @param node {RBNode} The node to insert. - * @return {void} - */ -RBTree.prototype.insertFixUp = function (node) { - for (var parent = node.parent; parent && parent.type === 'r'; parent = node.parent) { - if (parent === parent.parent.left) { - var uncle = parent.parent.right; - if (uncle && uncle.type === 'r') { - parent.type = 'b'; - uncle.type = 'b'; - parent.parent.type = 'r'; - node = parent.parent; - } else if (node === parent.right) { - node = parent; - this.leftRotate(node); - } else { - parent.type = 'b'; - parent.parent.type = 'r'; - this.rightRotate(parent.parent); - } - } else { - var uncle = parent.parent.left; - if (uncle && uncle.type === 'r') { - parent.type = 'b'; - uncle.type = 'b'; - parent.parent.type = 'r'; - node = parent.parent; - } else if (node === parent.left) { - node = parent; - this.rightRotate(node); - } else { - parent.type = 'b'; - parent.parent.type = 'r'; - this.leftRotate(parent.parent); - } - } - } - this.root.type = 'b'; -}; - -/** - * Deletes the node from the tree. - * @param node {RBNode} The node to delete. - * @return {void} - */ -RBTree.prototype.deleteNode = function (node) { - var successor; - this.size--; - if (!node.left || !node.right) - successor = node; - else { - successor = this.successor(node); - node.key = successor.key; - node.item = successor.item; - } - var child; - if (!successor.left) - child = successor.right; - else - child = successor.left; - if (child) - child.parent = successor.parent; - if (!successor.parent) - this.root = child; - else if (successor === successor.parent.left) - successor.parent.left = child; - else - successor.parent.right = child; - - if (successor.type === 'b') - this.deleteFixUp(child, successor.parent); -}; - -/** - * Preserves the properties of the tree after a deletion. - * @param node {RBNode} The node to delete. - * @param parent {RBNode} The parent of the node. - * @return {void} - */ -RBTree.prototype.deleteFixUp = function (node, parent) { - while (node !== this.root && (!node || node.type === 'b')) { - if (node === parent.left) { - var brother = parent.right; - if (brother && brother.type === 'r') { - brother.type = 'b'; - parent.type = 'r'; - this.leftRotate(parent); - brother = parent.right; - } - if (brother && (!brother.left || brother.left.type === 'b') && (!brother.right || brother.right.type === 'b')) { - brother.type = 'r'; - node = parent; - } else { - if (!brother.right || brother.right.type === 'b') { - brother.left.type = 'b'; - brother.type = 'r'; - this.rightRotate(brother); - brother = parent.right; - } - brother.type = parent.type; - parent.type = 'b'; - brother.right.type = 'b'; - this.leftRotate(parent); - node = this.root; - } - } else { - var brother = parent.left; - if (brother && brother.type === 'r') { - brother.type = 'b'; - parent.type = 'r'; - this.rightRotate(parent); - brother = parent.left; - } - if (brother && (!brother.left || brother.left.type === 'b') && (!brother.right || brother.right.type === 'b')) { - brother.type = 'r'; - node = parent; - } else { - if (!brother.left || brother.left.type === 'b') { - brother.right.type = 'b'; - brother.type = 'r'; - this.leftRotate(brother); - brother = parent.left; - } - brother.type = parent.type; - parent.type = 'b'; - brother.left.type = 'b'; - this.rightRotate(parent); - node = this.root; - } - } - parent = node.parent; - } - if (node) - node.type = 'b'; -}; - -/** - * Gets the node with the key next to the param node key. - * @param node {RBNode} The node of which search the successor. - * @return {RBNode} The node found. - */ -RBTree.prototype.successor = function (node) { - if (node.right) - return this.minimum(node.right); - var parent = node.parent; - while (parent && node === parent.right) { - node = parent; - parent = parent.parent; - } - return parent; -}; - -/** - * Gets the node with the key previous to the param node key. - * @param node {RBNode} The node of which search the predecessor. - * @return {RBNode} The node found. - */ -RBTree.prototype.predecessor = function (node) { - if (node.left) - return this.maximum(node.left); - var parent = node.parent; - while (parent && node === parent.left) { - node = parent; - parent = parent.parent; - } - return parent; -}; - -/** - * Searches the item relatives to the key and to the nodes that satisfy the condition represented by the callback function. - * @param key {number} The key to find. - * @param [node = root] {RBNode} The node from which start the search. - * @param [callback = function(node){return(node.key===key);}] The condition to satisfy. The callback must accept the current node to check. - * @return {*} The item found or undefined if there isn't the key in the tree. - */ -RBTree.prototype.search = function (key, node, callback) { - node = node || this.root; - callback = callback || function (node) { - return node.key === key; - }; - while (node && !callback(node)) - if (key < node.key) - node = node.left; - else - node = node.right; - if (node) - return node.item; - return undefined; -}; - -/** - * Checks if the tree contains a key or a node that satisfy the condition represented by the callback function. - * This method avoid to search in branches where the key won't be found. - * @param key {*} The key to find. - * @param [callback = function(node){return(node.key===key);}] The condition to satisfy. The callback must accept the current node to check. - * @return {boolean} True if the tree contains the key or a node that satisfy the condition, false otherwise. - */ -RBTree.prototype.contains = function (key, callback) { - return this.search(key, null, callback) !== undefined; -}; - -/** - * Checks if the tree contains a node that satisfy the condition represented by the callback function. - * This method check all the tree avoiding the binary search. - * @param callback {function} The condition to satisfy. The callback must accept the current node to check. - * @return {boolean} True if the tree contains the node that satisfy the condition, false otherwise. - */ -RBTree.prototype.fullContains = function (callback) { - var node = this.minimum(); - while (node && !callback(node.key)) - node = this.successor(node); - return node !== null; -}; - -/** - * Gets the item relatives to the minimum key stored in the tree. - * @param [node = root] {Node} The node from which start the search. - * @return {RBNode} The node found. - */ -RBTree.prototype.minimum = function (node) { - node = node || this.root; - while (node && node.left) - node = node.left; - return node; -}; - -/** - * Gets the item relatives to the maximum key stored in the tree. - * @param [node = root] {Node} The node from which start the search. - * @return {RBNode} The node found. - */ -RBTree.prototype.maximum = function (node) { - node = node || this.root; - while (node && node.right) - node = node.right; - return node; -}; - -/** - * Rotates the node with its right child. - * @param node {RBNode} The node to rotate. - * @return {void} - */ -RBTree.prototype.leftRotate = function (node) { - var child = node.right; - node.right = child.left; - if (child.left !== null) - child.left.parent = node; - child.parent = node.parent; - if (node.parent === null) - this.root = child; - else if (node === node.parent.left) - node.parent.left = child; - else - node.parent.right = child; - node.parent = child; - child.left = node; -}; - -/** - * Rotates the node with its left child. - * @param node {RBNode} The node to rotate. - * @return {void} - */ -RBTree.prototype.rightRotate = function (node) { - var child = node.left; - node.left = child.right; - if (child.right !== null) - child.right.parent = node; - child.parent = node.parent; - if (node.parent === null) - this.root = child; - else if (node === node.parent.left) - node.parent.left = child; - else - node.parent.right = child; - node.parent = child; - child.right = node; -}; - -/** - * Returns the size of the tree. - * @return {number} The size of the tree. - */ -RBTree.prototype.getSize = function () { - return this.size; -}; - -/** - * Clones the queue into a new queue. - * @return {RBTree} The tree cloned from this queue. - */ -RBTree.prototype.clone = function () { - var tree = new RBTree(); - var it = this.getIterator(); - for (it.first(); !it.isDone(); it.next()) - if (it.getNode().item.clone) - tree.insert(it.getNode().key, it.getNode().item.clone()); - else - tree.insert(it.getNode().key, it.getNode().item); - - return tree; -}; - -/** - * Clones the tree into a new tree without cloning duplicated items. - * @return {RBTree} The tree cloned from this tree. - */ -RBTree.prototype.cloneDistinct = function () { - var tree = new RBTree(); - var it = this.getIterator(); - for (it.first(); !it.isDone(); it.next()) { - var callback = function (node) { - return node.key === it.getNode().key && node.item === it.getNode().item; - }; - if (!tree.contains(it.getNode().key, callback)) { - if (it.getNode().item.cloneDistinct) - tree.insert(it.getNode().key, it.getNode().item.cloneDistinct()); - else if (it.getNode().item.clone) - tree.insert(it.getNode().key, it.getNode().item.clone()); - else - tree.insert(it.getNode().key, it.getNode().item); - } - } - return tree; -}; - -/** - * Transforms the tree into an array without preserving keys. - * @return {Array<*>} The array that represents the tree. - */ -RBTree.prototype.toArray = function () { - var result = []; - for (var node = this.minimum(); node; node = this.successor(node)) - result.push(node.item); - return result; -}; - -/** - * Removes all the items stored in the tree. - * @return {void} - */ -RBTree.prototype.clear = function () { - this.root = null; - this.size = 0; -}; - -/** - * Checks if the tree is empty. - * @return {boolean} True if the tree is empty, false otherwise. - */ -RBTree.prototype.isEmpty = function () { - return !this.size; -}; - -/** - * Executes the callback function for each item of the tree. - * This method modifies the tree so if you don't need to modify it you must return the same item stored. - * @param callback {function} The function to execute for each item. The function must accept the current item on which execute the function. - * @return {void} - */ -RBTree.prototype.execute = function (callback) { - for (var node = this.minimum(); node; node = this.successor(node)) - node.item = callback(node.item); -}; - -/** - * Returns the items that satisfy the condition determined by the callback. - * @param callback {function} The function that implements the condition. - * @return {Array<*>} The array that contains the items that satisfy the condition. - */ -RBTree.prototype.filter = function (callback) { - var result = []; - for (var node = this.minimum(); node; node = this.successor(node)) - if (callback(node.item)) - result.push(node.item); - return result; -}; - -/** - * Returns the first position of the item in the tree. - * @param item {*} The item to search. - * @param [callback = function(item){return(it===item);}] The condition to satisfy. The callback must accept the current item to check. - * @return {number} The first position of the item. - */ -RBTree.prototype.indexOf = function (item, callback) { - callback = callback || function (it) { - return it === item; - }; - var i = 0, node = this.minimum(); - while (node) { - if (callback(node.item)) - return i; - node = this.successor(node); - i++; - } - return -1; -}; - -/** - * Returns the last position of the item in the tree. - * @param item {*} The item to search. - * @param [callback = function(item){return(it===item);}] The condition to satisfy. The callback must accept the current item to check. - * @return {number} The last position of the item. - */ -RBTree.prototype.lastIndexOf = function (item, callback) { - callback = callback || function (it) { - return it === item; - }; - var i = this.size - 1, node = this.maximum(); - while (node) { - if (callback(node.item)) - return i; - i--; - node = this.predecessor(node); - } - return -1; -}; - -/** - * Returns all the position in which the item has been found in the tree. - * @param item {*} The item to search. - * @param [callback = function(item){return(it===item);}] The condition to satisfy. The callback must accept the current item to check. - * @return {Array} The positions in which the item has been found. - */ -RBTree.prototype.allIndexesOf = function (item, callback) { - callback = callback || function (it) { - return it === item; - }; - var i = 0, node = this.minimum(); - var indexes = []; - while (node) { - if (callback(node.item)) - indexes.push(i); - i++; - node = this.successor(node); - } - return indexes; -}; - -/** - * Returns the item at the position index. - * @param index {number} The position of the item. - * @return {*} The item at the position. It's undefined if index isn't in the tree bounds. - */ -RBTree.prototype.getItem = function (index) { - if (index < 0 || index > this.size - 1) - return undefined; - for (var node = this.minimum(), i = 0; i < index; node = this.successor(node)) - i++; - return node.item; -}; - -/** - * Class that implements the iterator for a red-black tree. - * @param aggregate {RBTree} The aggregate to scan. - * @constructor - */ -function RBTreeIterator(aggregate) { - /** - * The aggregate relates to this iterator. - * @type {RBTree} - */ - this.aggregate = aggregate; - - /** - * The pointer to the position. - * @type {RBNode|null} - */ - this.pointer = null; -} - -/** - * Moves the iterator to the first position of the aggregate. - * @return {void} - */ -RBTreeIterator.prototype.first = function () { - this.pointer = this.aggregate.minimum(); -}; - -/** - * Moves the iterator to the next item. - * @return {void} - */ -RBTreeIterator.prototype.next = function () { - this.pointer = this.aggregate.successor(this.pointer); -}; - -/** - * Moves the iterator to the last position of the aggregate. - * @return {void} - */ -RBTreeIterator.prototype.last = function () { - this.pointer = this.aggregate.maximum(); -}; - -/** - * Moves the iterator to the previous item. - * @return {void} - */ -RBTreeIterator.prototype.previous = function () { - this.pointer = this.aggregate.predecessor(this.pointer); -}; - -/** - * Checks if the iterator is out of the bounds of the aggregate. - * @return {boolean} It return true if the iterator is out of the bounds of the aggregate, otherwise false. - */ -RBTreeIterator.prototype.isDone = function () { - return !this.pointer; -}; - -/** - * Returns the item stored at the position pointed by the iterator. - * @return {Object|undefined} The item stored or undefined if it's out of the bounds. - */ -RBTreeIterator.prototype.getItem = function () { - return this.pointer.item; -}; - -/** - * Returns the node stored at the position pointed by the iterator. - * @return {RBNode|null} The node stored or null if it's out of the bounds. - */ -RBTreeIterator.prototype.getNode = function () { - return this.pointer; -}; - -/** - * Class for managing a red-black tree where nodes are also in a list. - * @constructor - */ -function RBTreeList() { - /** - * The root of the tree. - * @type {RBLNode|null} - */ - this.root = null; - /** - * The first node of the tree. - * @type {RBLNode|null} - */ - this.first = null; - /** - * The last node of the tree. - * @type {RBLNode|null} - */ - this.last = null; - /** - * The size of the tree. - * @type {number} - */ - this.size = 0; -} - -/** - * Returns the iterator relative to the aggregate. - * @return {Iterator} The iterator. - */ -RBTreeList.prototype.getIterator = function () { - return new RBTreeListIterator(this); -}; - -/** - * Inserts the item relatives to the key value in the tree. - * @param key {number} The key to store. - * @param item {*} The item to store. - * @return {void} - */ -RBTreeList.prototype.insert = function (key, item) { - var node = new RBLNode(key, item); - this.size++; - if (!this.root) { - this.root = node; - this.first = node; - this.last = node; - node.type = 'b'; - return; - } - var p = this.root; - for (var n = this.root; n;) { - p = n; - if (key < n.key) - n = n.left; - else - n = n.right; - } - node.parent = p; - if (!p) - this.root = node; - else if (key < p.key) - p.left = node; - else - p.right = node; - - node.next = this.successor(node); - if (node.next) { - if (node.next.previous) - node.next.previous.next = node; - else - this.first = node; - node.previous = node.next.previous; - node.next.previous = node; - } else { - this.last = node; - node.previous = this.predecessor(node); - if (node.previous) - node.previous.next = node; - else - this.first = node; - } - - this.insertFixUp(node); -}; - -/** - * Preserves the properties of the tree after an insert. - * @param node {RBLNode} The node to insert. - * @return {void} - */ -RBTreeList.prototype.insertFixUp = function (node) { - for (var parent = node.parent; parent && parent.type === 'r'; parent = node.parent) { - if (parent === parent.parent.left) { - var uncle = parent.parent.right; - if (uncle && uncle.type === 'r') { - parent.type = 'b'; - uncle.type = 'b'; - parent.parent.type = 'r'; - node = parent.parent; - } else if (node === parent.right) { - node = parent; - this.leftRotate(node); - } else { - parent.type = 'b'; - parent.parent.type = 'r'; - this.rightRotate(parent.parent); - } - } else { - var uncle = parent.parent.left; - if (uncle && uncle.type === 'r') { - parent.type = 'b'; - uncle.type = 'b'; - parent.parent.type = 'r'; - node = parent.parent; - } else if (node === parent.left) { - node = parent; - this.rightRotate(node); - } else { - parent.type = 'b'; - parent.parent.type = 'r'; - this.leftRotate(parent.parent); - } - } - } - this.root.type = 'b'; -}; - -/** - * Deletes the node from the tree. - * @param node {RBLNode} The node to delete. - * @return {void} - */ -RBTreeList.prototype.deleteNode = function (node) { - this.size--; - var successor; - if (!node.left || !node.right) - successor = node; - else { - successor = this.successor(node); - node.key = successor.key; - node.item = successor.item; - } - var child; - if (!successor.left) - child = successor.right; - else - child = successor.left; - if (child) - child.parent = successor.parent; - if (!successor.parent) - this.root = child; - else if (successor === successor.parent.left) - successor.parent.left = child; - else - successor.parent.right = child; - - if (successor.next) - successor.next.previous = successor.previous; - else - this.last = successor.previous; - if (successor.previous) - successor.previous.next = successor.next; - else - this.first = successor.next; - - if (successor.type === 'b') - this.deleteFixUp(child, successor.parent); -}; - -/** - * Preserves the properties of the tree after a deletion. - * @param node {RBLNode} The node to delete. - * @param parent {RBLNode} The parent of the node. - * @return {void} - */ -RBTreeList.prototype.deleteFixUp = function (node, parent) { - while (node !== this.root && (!node || node.type === 'b')) { - if (node === parent.left) { - var brother = parent.right; - if (brother && brother.type === 'r') { - brother.type = 'b'; - parent.type = 'r'; - this.leftRotate(parent); - brother = parent.right; - } - if (brother && (!brother.left || brother.left.type === 'b') && (!brother.right || brother.right.type === 'b')) { - brother.type = 'r'; - node = parent; - } else { - if (!brother.right || brother.right.type === 'b') { - brother.left.type = 'b'; - brother.type = 'r'; - this.rightRotate(brother); - brother = parent.right; - } - brother.type = parent.type; - parent.type = 'b'; - brother.right.type = 'b'; - this.leftRotate(parent); - node = this.root; - } - } else { - var brother = parent.left; - if (brother && brother.type === 'r') { - brother.type = 'b'; - parent.type = 'r'; - this.rightRotate(parent); - brother = parent.left; - } - if (brother && (!brother.left || brother.left.type === 'b') && (!brother.right || brother.right.type === 'b')) { - brother.type = 'r'; - node = parent; - } else { - if (!brother.left || brother.left.type === 'b') { - brother.right.type = 'b'; - brother.type = 'r'; - this.leftRotate(brother); - brother = parent.left; - } - brother.type = parent.type; - parent.type = 'b'; - brother.left.type = 'b'; - this.rightRotate(parent); - node = this.root; - } - } - parent = node.parent; - } - if (node) - node.type = 'b'; -}; - -/** - * Gets the node with the key next to the param node key. - * @param node {RBLNode} The node of which search the successor. - * @return {RBLNode} The node found. - */ -RBTreeList.prototype.successor = function (node) { - if (node.next || node === this.last) - return node.next; - if (node.right) - return this.minimum(node.right); - var parent = node.parent; - while (parent && node === parent.right) { - node = parent; - parent = parent.parent; - } - return parent; -}; - -/** - * Gets the node with the key previous to the param node key. - * @param node {RBLNode} The node of which search the predecessor. - * @return {RBLNode} The node found. - */ -RBTreeList.prototype.predecessor = function (node) { - if (node.previous || node === this.first) - return node.previous; - if (node.left) - return this.maximum(node.left); - var parent = node.parent; - while (parent && node === parent.left) { - node = parent; - parent = parent.parent; - } - return parent; -}; - -/** - * Searches the item relatives to the key that satisfy the condition represented by the callback function. - * @param key {number} The key to find. - * @param [node = root] {RBNode} The node from which start the search. - * @param [callback = function(k){return(k===key);}] The condition to satisfy. The callback must accept the current key to check. - * @return {*} The item found or undefined if there isn't the key in the tree. - */ -RBTreeList.prototype.search = function (key, node, callback) { - node = node || this.root; - callback = callback || function (node) { - return node.key === key; - }; - while (node && !callback(node)) - if (key < node.key) - node = node.left; - else - node = node.right; - if (node) - return node.item; - return undefined; -}; - -/** - * Checks if the tree contains a key or a node that satisfy the condition represented by the callback function. - * This method avoid to search in branches where the key won't be found. - * @param key {*} The key to find. - * @param [callback = function(node){return(node.key===key);}] The condition to satisfy. The callback must accept the current node to check. - * @return {boolean} True if the tree contains the key or a node that satisfy the condition, false otherwise. - */ -RBTreeList.prototype.contains = function (key, callback) { - return this.search(key, null, callback) !== undefined; -}; - -/** - * Checks if the tree contains a node that satisfy the condition represented by the callback function. - * This method check all the tree avoiding the binary search. - * @param callback {function} The condition to satisfy. The callback must accept the current node to check. - * @return {boolean} True if the tree contains the node that satisfy the condition, false otherwise. - */ -RBTreeList.prototype.fullContains = function (callback) { - var node = this.first; - while (node && !callback(node.key)) - node = node.next; - return node !== null; -}; - -/** - * Gets the item relatives to the minimum key stored in the tree. - * @param [node = root] {Node} The node from which start the search. - * @return {RBLNode} The node found. - */ -RBTreeList.prototype.minimum = function (node) { - if (node) - while (node && node.left) - node = node.left; - else - return this.first; - return node; -}; - -/** - * Gets the item relatives to the maximum key stored in the tree. - * @param [node = root] {Node} The node from which start the search. - * @return {RBLNode} The node found. - */ -RBTreeList.prototype.maximum = function (node) { - if (node) - while (node && node.right) - node = node.right; - else - return this.last; - return node; -}; - -/** - * Rotates the node with its right child. - * @param node {RBLNode} The node to rotate. - * @return {void} - */ -RBTreeList.prototype.leftRotate = function (node) { - var child = node.right; - node.right = child.left; - if (child.left !== null) - child.left.parent = node; - child.parent = node.parent; - if (node.parent === null) - this.root = child; - else if (node === node.parent.left) - node.parent.left = child; - else - node.parent.right = child; - node.parent = child; - child.left = node; -}; - -/** - * Rotates the node with its left child. - * @param node {RBLNode} The node to rotate. - * @return {void} - */ -RBTreeList.prototype.rightRotate = function (node) { - var child = node.left; - node.left = child.right; - if (child.right !== null) - child.right.parent = node; - child.parent = node.parent; - if (node.parent === null) - this.root = child; - else if (node === node.parent.left) - node.parent.left = child; - else - node.parent.right = child; - node.parent = child; - child.right = node; -}; - -/** - * Returns the size of the tree. - * @return {number} The size of the tree. - */ -RBTreeList.prototype.getSize = function () { - return this.size; -}; - -/** - * Clones the tree into a new tree. - * @return {RBTreeList} The tree cloned from this tree. - */ -RBTreeList.prototype.clone = function () { - var tree = new RBTreeList(); - var it = this.getIterator(); - for (it.first(); !it.isDone(); it.next()) - tree.insert(it.getNode().key, it.getNode().item); - return tree; -}; - -/** - * Clones the tree into a new tree without cloning duplicated items. - * @return {RBTreeList} The tree cloned from this tree. - */ -RBTreeList.prototype.cloneDistinct = function () { - var tree = new RBTreeList(); - var it = this.getIterator(); - for (it.first(); !it.isDone(); it.next()) { - var callback = function (node) { - return node.key === it.getNode().key && node.item === it.getNode().item; - }; - if (!tree.contains(it.getNode().key, callback)) { - if (it.getNode().item.cloneDistinct) - tree.insert(it.getNode().key, it.getNode().item.cloneDistinct()); - else if (it.getNode().item.clone) - tree.insert(it.getNode().key, it.getNode().item.clone()); - else - tree.insert(it.getNode().key, it.getNode().item); - } - } - return tree; -}; - -/** - * Transforms the tree into an array without preserving keys. - * @return {Array<*>} The array that represents the tree. - */ -RBTreeList.prototype.toArray = function () { - var result = []; - for (var node = this.first; node; node = node.next) - result.push(node.item); - return result; -}; - -/** - * Removes all the items stored in the tree. - * @return {void} - */ -RBTreeList.prototype.clear = function () { - this.root = null; - this.first = null; - this.last = null; - this.size = 0; -}; - -/** - * Checks if the tree is empty. - * @return {boolean} True if the tree is empty, false otherwise. - */ -RBTreeList.prototype.isEmpty = function () { - return !this.size; -}; - -/** - * Executes the callback function for each item of the tree. - * This method modifies the tree so if you don't need to modify it you must return the same item stored. - * @param callback {function} The function to execute for each item. The function must accept the current item on which execute the function. - * @return {void} - */ -RBTreeList.prototype.execute = function (callback) { - for (var node = this.first; node; node = node.next) - node.item = callback(node.item); -}; - -/** - * Returns the items that satisfy the condition determined by the callback. - * @param callback {function} The function that implements the condition. - * @return {Array<*>} The array that contains the items that satisfy the condition. - */ -RBTreeList.prototype.filter = function (callback) { - var result = []; - for (var node = this.first; node; node = node.next) - if (callback(node.item)) - result.push(node.item); - return result; -}; - -/** - * Returns the first position of the item in the tree. - * @param item {*} The item to search. - * @param [callback = function(item){return(it===item);}] The condition to satisfy. The callback must accept the current item to check. - * @return {number} The first position of the item. - */ -RBTreeList.prototype.indexOf = function (item, callback) { - callback = callback || function (it) { - return it === item; - }; - var i = 0, node = this.first; - while (node) { - if (callback(node.item)) - return i; - node = node.next; - i++; - } - return -1; -}; - -/** - * Returns the last position of the item in the tree. - * @param item {*} The item to search. - * @param [callback = function(item){return(it===item);}] The condition to satisfy. The callback must accept the current item to check. - * @return {number} The last position of the item. - */ -RBTreeList.prototype.lastIndexOf = function (item, callback) { - callback = callback || function (it) { - return it === item; - }; - var i = this.size - 1, node = this.last; - while (node) { - if (callback(node.item)) - return i; - i--; - node = node.previous; - } - return -1; -}; - -/** - * Returns all the position in which the item has been found in the tree. - * @param item {*} The item to search. - * @param [callback = function(item){return(it===item);}] The condition to satisfy. The callback must accept the current item to check. - * @return {Array} The positions in which the item has been found. - */ -RBTreeList.prototype.allIndexesOf = function (item, callback) { - callback = callback || function (it) { - return it === item; - }; - var i = 0, node = this.first; - var indexes = []; - while (node) { - if (callback(node.item)) - indexes.push(i); - i++; - node = node.next; - } - return indexes; -}; - -/** - * Returns the item at the position index. - * @param index {number} The position of the item. - * @return {*} The item at the position. It's undefined if index isn't in the tree bounds. - */ -RBTreeList.prototype.getItem = function (index) { - if (index < 0 || index > this.size - 1) - return undefined; - for (var node = this.first, i = 0; i < index; node = node.next) - i++; - return node.item; -}; - -/** - * Class that implements the iterator for a red-black tree. - * @param aggregate {RBTreeList} The aggregate to scan. - * @constructor - */ -function RBTreeListIterator(aggregate) { - /** - * The aggregate relates to this iterator. - * @type {RBTreeList} - */ - this.aggregate = aggregate; - /** - * The pointer to the position. - * @type {RBLNode|null} - */ - this.pointer = null; -} - -/** - * Moves the iterator to the first position of the aggregate. - * @return {void} - */ -RBTreeListIterator.prototype.first = function () { - this.pointer = this.aggregate.first; -}; - -/** - * Moves the iterator to the next item. - * @return {void} - */ -RBTreeListIterator.prototype.next = function () { - this.pointer = this.pointer.next; -}; - -/** - * Moves the iterator to the last position of the aggregate. - * @return {void} - */ -RBTreeListIterator.prototype.last = function () { - this.pointer = this.aggregate.last; -}; - -/** - * Moves the iterator to the previous item. - * @return {void} - */ -RBTreeListIterator.prototype.previous = function () { - this.pointer = this.pointer.previous; -}; - -/** - * Checks if the iterator is out of the bounds of the aggregate. - * @return {boolean} It return true if the iterator is out of the bounds of the aggregate, otherwise false. - */ -RBTreeListIterator.prototype.isDone = function () { - return !this.pointer; -}; - -/** - * Returns the item stored at the position pointed by the iterator. - * @return {*} The item stored or undefined if it's out of the bounds. - */ -RBTreeListIterator.prototype.getItem = function () { - return this.pointer.item; -}; - -/** - * Returns the node stored at the position pointed by the iterator. - * @abstract - * @return {RBNode|null} The node stored or null if it's out of the bounds. - */ -RBTreeListIterator.prototype.getNode = function () { - return this.pointer; -}; - -/** - * Class for managing a set. - * @constructor - */ -function Set() { - /** - * The parents of the set. - * @type {DoubleLinkedList} - */ - this.parents = new DoubleLinkedList(); - /** - * The elements stored. - * @type {DoubleLinkedList} - */ - this.elements = new DoubleLinkedList(); - /** - * The subsets of this set. - * @type {DoubleLinkedList} - */ - this.sets = new DoubleLinkedList(); - /** - * The size of the set. It's equal to his cardinality. - * @type {number} - */ - this.size = 0; -} - -/** - * Adds the element to the set. - * @param element {Element} The element to add. - * @return {void} - */ -Set.prototype.insert = function (element) { - this.elements.pushBack(element); - element.parents.pushBack(this); - this.size++; -}; - -/** - * Adds the elements to the set. - * @param elements {Array} The elements to add. - * @return {void} - */ -Set.prototype.multiInsert = function (elements) { - for (var i = 0; i < elements.length; i++) { - this.elements.pushBack(elements[i]); - elements[i].parents.pushBack(this); - } - this.size += elements.length; -}; - -/** - * Returns the set that represents the union of two sets. - * @param set {Set} The set with make the union. - * @return {Set} The set that represents the union. - */ -Set.prototype.union = function (set) { - var parent = new Set(); - parent.addSubsets([this, set]); - this.parents.pushBack(parent); - set.parents.pushBack(parent); - //change the parent of the subset - var that = this; - var f = function (item) { - if (item === that) - return parent; - }; - var it = this.sets.getIterator(); - for (it.first(); !it.isDone(); it.next()) - it.getItem().parents.execute(f); - f = function (item) { - if (item === set) - return parent; - }; - it = set.sets.getIterator(); - for (it.first(); !it.isDone(); it.next()) - it.getItem().parents.execute(f); - return parent; -}; - -/** - * Returns the set that represents the intersection of two sets. - * @param set {Set} The set to intersect with this. - * @return {Set} The set that represents the intersection. - */ -Set.prototype.intersect = function (set) { - var intersection = new Set(); - //intersect this set with the set - var el = this.elements.getIterator(); - for (el.first(); !el.isDone(); el.next()) - if (el.getItem().parents.contains(set)) - intersection.insert(el.getItem()); - - //intersect the subsets with the set - var it = this.sets.getIterator(); - for (it.first(); !it.isDone(); it.next()) { - el = it.getItem().getIterator(); - for (el.first(); !el.isDone(); el.next()) - if (el.getItem().parents.contains(set)) - intersection.insert(el.getItem()); - } - return intersection; -}; - -/** - * Returns the set that represents the difference of two sets. - * @param set {Set} The set to difference with this. - * @return {Set} The set that represents the difference. - */ -Set.prototype.difference = function (set) { - var diff = new Set(); - //intersect this set with the set - var el = this.elements.getIterator(); - for (el.first(); !el.isDone(); el.next()) - if (!el.getItem().parents.contains(set)) - diff.insert(el.getItem()); - - //intersect the subsets with the set - var it = this.sets.getIterator(); - for (it.first(); !it.isDone(); it.next()) { - el = it.getItem().getIterator(); - for (el.first(); !el.isDone(); el.next()) - if (!el.getItem().parents.contains(set)) - diff.insert(el.getItem()); - } - return diff; -}; - -/** - * Returns the set that represents the cartesian product of two sets. - * @param set {Set} The set to make the cartesian product with this. - * @return {Set} The set that represents the cartesian product . - */ -Set.prototype.cartesianProduct = function (set) { - var el1 = this.getItems(); - var el2 = set.getItems(); - var product = new Set(); - for (var i = 0; i < el1.length; i++) - for (var j = 0; j < el2.length; j++) - product.insert(new Element([el1[i], el2[j]])); - return product; -}; - -/** - * Adds the subset. - * @param set {Set} The subset. - */ -Set.prototype.addSubset = function (set) { - this.sets.pushBack(set); - this.size += set.size; -}; - -/** - * Adds the subsets. - * @param sets {Array} The subsets. - */ -Set.prototype.addSubsets = function (sets) { - for (var i = 0; i < sets.length; i++) - this.addSubset(sets[i]); -}; - -/** - * Returns the items that are stored in the set. - * @return {Array} The items stored. - */ -Set.prototype.getItems = function () { - var array = []; - //get the items stored in the set - var el = this.elements.getIterator(); - for (el.first(); !el.isDone(); el.next()) - array.push(el.getItem().item); - - //get the items stored in the subsets - var it = this.sets.getIterator(); - for (it.first(); !it.isDone(); it.next()) { - el = it.getItem().getIterator(); - for (el.first(); !el.isDone(); el.next()) - array.push(el.getItem().item); - } - return array; -}; - -/** - * Returns the cardinality of the set. - * @return {number} The cardinality of the set. - */ -Set.prototype.getCardinality = function () { - return this.size; -}; - -/** - * Checks if the set is empty. - * @return {boolean} True if the set is empty, false otherwise. - */ -Set.prototype.isEmpty = function () { - return !this.size; -}; - -/** - * Clones the set into a new set. - * @return {Set} The set cloned from this set. - */ -Set.prototype.clone = function () { - var s = new Set(); - s.parents = this.parents.clone(); - s.elements = this.elements.clone(); - s.sets = this.sets.clone(); - s.size = this.size; - return s; -}; - -/** - * Class for managing a stack. - * @param {...*} [args] The items for initializing the stack. - * @constructor - */ -function Stack(args) { - /** - * The list of the items in the stack. - * @type {Array<*>} - */ - this.items = []; - - //builds the stack from the parameters of the constructor - this.multiPush(arguments); -} - -/** - * Returns the iterator relative to the aggregate. - * @return {Iterator} The iterator. - */ -Stack.prototype.getIterator = function () { - return new StackIterator(this); -}; - -/** - * Adds the item at the top of the stack. - * @param item {*} The item to add. - * return {void} - */ -Stack.prototype.push = function (item) { - this.items.push(item); -}; - -/** - * Adds the items at the top of the stack. - * @param items {Array<*>} The items to add. - * @return {void} - */ -Stack.prototype.multiPush = function (items) { - for (var i = 0; i < items.length; i++) - this.push(items[i]); -}; - -/** - * Removes the item at the top of the stack. - * @return {*} The item at the top of the stack. It's undefined if the stack is empty. - */ -Stack.prototype.pop = function () { - if (!this.items.length) - return undefined; - return this.items.pop(); -}; - -/** - * Removes the more item at the top of the stack. - * @param times {number} The number of times to repeat the pop method. - * @return {Array<*>} The items at the top of the stack. - */ -Stack.prototype.multiPop = function (times) { - var result = []; - for (var i = 0; i < times && this.items.length; i++) - result.push(this.pop()); - return result; -}; - -/** - * Returns the item at the top of the stack without remove it. - * @return {*} The item at the top of the stack. It's undefined if the stack is empty. - */ -Stack.prototype.peek = function () { - if (!this.items.length) - return undefined; - return this.items[this.items.length - 1]; -}; - -/** - * Removes all the items stored in the stack. - * @return {void} - */ -Stack.prototype.clear = function () { - this.items = []; -}; - -/** - * Checks if the stack contains an item that satisfy the condition represented by the callback function. - * @param item {*} The item to find. - * @param [callback = function(item){return(it===item);}] The condition to satisfy. The callback must accept the current item to check. - * @return {boolean} True if the stack contains the item that satisfy the condition, false otherwise. - */ -Stack.prototype.contains = function (item, callback) { - callback = callback || function (it) { - return it === item; - }; - var i = 0; - while (i < this.items.length && !callback(this.items[i])) - i++; - return i < this.items.length; -}; - -/** - * Executes the callback function for each item of the stack. - * This method modifies the stack so if you don't need to modify it you must return the same item of the array. - * @param callback {function} The function to execute for each item. The function must accept the current item on which execute the function. - * @return {void} - */ -Stack.prototype.execute = function (callback) { - for (var i = this.items.length - 1; i > -1; i--) - this.items[i] = callback(this.items[i]); -}; - -/** - * Returns the item at the position index. - * @param index The position of the item. - * @return {*} The item at the position. It's undefined if index isn't in the stack bounds. - */ -Stack.prototype.getItem = function (index) { - if (index < 0 || index > this.items.length - 1) - return undefined; - return this.items[this.items.length - index - 1]; -}; - -/** - * Returns the length of the stack. - * @return {Number} The length of the stack. - */ -Stack.prototype.getLength = function () { - return this.items.length; -}; - -/** - * Checks if the stack is empty. - * @return {boolean} True if the stack is empty, false otherwise. - */ -Stack.prototype.isEmpty = function () { - return !this.items.length; -}; - -/** - * Returns the items that satisfy the condition determined by the callback. - * @param callback {function} The function that implements the condition. - * @return {Array<*>} The array that contains the items that satisfy the condition. - */ -Stack.prototype.filter = function (callback) { - var result = []; - for (var i = this.items.length - 1; i > -1; i--) { - if (callback(this.items[i])) - result.push(this.items[i]); - } - return result; -}; - -/** - * Returns the first position of the item in the stack. - * @param item {*} The item to search. - * @param [callback = function(item){return(it===item);}] The condition to satisfy. The callback must accept the current item to check. - * @return {number} The first position of the item. - */ -Stack.prototype.indexOf = function (item, callback) { - callback = callback || function (it) { - return it === item; - }; - var i = this.items.length - 1; - while (i > -1) { - if (callback(this.items[i])) - return i; - i--; - } - return -1; -}; - -/** - * Returns the last position of the item in the stack. - * @param item {*} The item to search. - * @param [callback = function(item){return(it===item);}] The condition to satisfy. The callback must accept the current item to check. - * @return {number} The last position of the item. - */ -Stack.prototype.lastIndexOf = function (item, callback) { - callback = callback || function (it) { - return it === item; - }; - var i = 0; - while (i < this.items.length) { - if (callback(this.items[i])) - return i; - i++; - } - return -1; -}; - -/** - * Returns all the position in which the item has been found in the stack. - * @param item {*} The item to search. - * @param [callback = function(item){return(it===item);}] The condition to satisfy. The callback must accept the current item to check. - * @return {Array} The positions in which the item has been found. - */ -Stack.prototype.allIndexesOf = function (item, callback) { - callback = callback || function (it) { - return it === item; - }; - var i = this.items.length - 1; - var indexes = []; - while (i > -1) { - if (callback(this.items[i])) - indexes.push(i); - i--; - } - return indexes; -}; - -/** - * Clones the stack into a new stack. - * @return {Stack} The stack cloned from this stack. - */ -Stack.prototype.clone = function () { - var stack = new Stack(); - for (var i = 0; i < this.items.length; i++) - if (this.items[i].clone) - stack.push(this.items[i].clone()); - else - stack.push(this.items[i]); - return stack; -}; - -/** - * Clones the stack into a new stack without cloning duplicated items. - * @return {Stack} The stack cloned from this stack. - */ -Stack.prototype.cloneDistinct = function () { - var stack = new Stack(); - for (var i = 0; i < this.items.length; i++) - if (!stack.contains(this.items[i])) { - if (this.items[i].cloneDistinct) - stack.push(this.items[i].cloneDistinct()); - else if (this.items[i].clone) - stack.push(this.items[i].clone()); - else - stack.push(this.items[i]); - } - return stack; -}; - -/** - * Class that implements the iterator for a linked list. - * @param aggregate {Stack} The aggregate to scan. - * @constructor - */ -function StackIterator(aggregate) { - /** - * The aggregate relates to this iterator. - * @type {Stack} - */ - this.aggregate = aggregate; - - /** - * The pointer to the position. - * @type {number} - */ - this.pointer = -1; -} - -/** - * Moves the iterator to the first position of the aggregate. - * @return {void} - */ -StackIterator.prototype.first = function () { - this.pointer = this.aggregate.items.length - 1; -}; - -/** - * Moves the iterator to the next item. - * @return {void} - */ -StackIterator.prototype.next = function () { - this.pointer--; -}; - -/** - * Moves the iterator to the last position of the aggregate. - * @return {void} - */ -StackIterator.prototype.last = function () { - this.pointer = 0; -}; - -/** - * Moves the iterator to the previous item. - * @return {void} - */ -StackIterator.prototype.previous = function () { - this.pointer++; -}; - -/** - * Checks if the iterator is out of the bounds of the aggregate. - * @return {boolean} It return true if the iterator is out of the bounds of the aggregate, otherwise false. - */ -StackIterator.prototype.isDone = function () { - return this.pointer < 0 || this.pointer > this.aggregate.items.length - 1; -}; - -/** - * Returns the item stored at the position pointed by the iterator. - * @return {*} The item stored or undefined if it's out of the bounds. - */ -StackIterator.prototype.getItem = function () { - return this.aggregate.items[this.pointer]; -}; diff --git a/DataStructuresMinimized.js b/DataStructuresMinimized.js deleted file mode 100644 index 4a727e1..0000000 --- a/DataStructuresMinimized.js +++ /dev/null @@ -1,2751 +0,0 @@ -function Aggregate() { -} -function Iterator() { -} -function BSNode(e, t) { - this.item = t; - this.key = e; - this.parent = null; - this.left = null; - this.right = null -} -function BSTree() { - this.root = null -} -function BSTreeIterator(e) { - this.aggregate = e; - this.pointer = null -} -function BNode() { - this.keys = []; - this.items = []; - this.childs = [] -} -function BTree(e) { - this.root = new BNode; - this.t = e; - this.size = 0 -} -function BTreeIterator(e) { - this.aggregate = e; - this.pointer = null -} -function CircularBufferIterator(e) { - this.aggregate = e; - this.pointer = null; - this.start = true -} -function CircularBuffer(e) { - this.head = 0; - this.tail = 0; - this.items = new Array(e); - this.empty = true; - this.full = false; - this.size = e -} -function DLLNode(e) { - this.item = e; - this.next = null; - this.previous = null -} -function DoubleLinkedList(e) { - this.first = null; - this.last = null; - this.length = 0; - this.fromArray(arguments) -} -function DoubleLinkedListIterator(e) { - this.aggregate = e; - this.pointer = null -} -function merge(e, t, n) { - var r = Math.floor((e + t) / 2); - var i = []; - var s = []; - for (var o = 0; o < r - e + 1; o++)i[o] = n[e + o]; - for (var u = 0; u < t - r; u++)s[u] = n[r + u + 1]; - var a = 0, f = 0; - for (var l = e; l < t + 1; l++) { - if (f > t - r - 1 || i[a] <= s[f] && a < r - e + 1) { - this.postMessage({cmd: "replace", index: l, value: i[a]}); - a++ - } else { - this.postMessage({cmd: "replace", index: l, value: s[f]}); - f++ - } - } -} -function HashTable(e) { - this.size = e; - this.p = 1e3; - this.a = Math.floor(Math.random() * this.p); - this.b = Math.floor(Math.random() * this.p); - this.hash = function (e) { - return(this.a * e + this.b) % this.p % this.size - }; - this.items = []; - this.keyLength = 0; - this.clear() -} -function LLNode(e) { - this.item = e; - this.next = null -} -function LinkedList(e) { - this.first = null; - this.last = null; - this.length = 0; - this.fromArray(arguments) -} -function LinkedListIterator(e) { - this.aggregate = e; - this.pointer = null -} -function PriorityQueue() { - this.items = new RBTreeList; - this.length = 0 -} -function PriorityQueueIterator(e) { - this.aggregate = e; - this.pointerNode = null; - this.pointerPosition = -1 -} -function Queue(e) { - this.items = []; - this.multiEnqueue(arguments) -} -function QueueIterator(e) { - this.aggregate = e; - this.pointer = -1 -} -function RBNode(e, t) { - this.item = t; - this.key = e; - this.parent = null; - this.left = null; - this.right = null; - this.type = "r" -} -function RBTree() { - this.root = null; - this.size = 0 -} -function RBTreeIterator(e) { - this.aggregate = e; - this.pointer = null -} -function RBLNode(e, t) { - this.item = t; - this.key = e; - this.parent = null; - this.left = null; - this.right = null; - this.next = null; - this.previous = null; - this.type = "r" -} -function RBTreeList() { - this.root = null; - this.first = null; - this.last = null; - this.size = 0 -} -function RBTreeListIterator(e) { - this.aggregate = e; - this.pointer = null -} -function Element(e) { - this.parents = new DoubleLinkedList; - this.item = e -} -function Set() { - this.parents = new DoubleLinkedList; - this.elements = new DoubleLinkedList; - this.sets = new DoubleLinkedList; - this.size = 0 -} -function Stack(e) { - this.items = []; - this.multiPush(arguments) -} -function StackIterator(e) { - this.aggregate = e; - this.pointer = -1 -} -Aggregate.prototype.getIterator = function () { -}; -Iterator.prototype.first = function () { -}; -Iterator.prototype.next = function () { -}; -Iterator.prototype.last = function () { -}; -Iterator.prototype.previous = function () { -}; -Iterator.prototype.isDone = function () { -}; -Iterator.prototype.getItem = function () { -}; -BSTree.prototype = new Aggregate; -BSTree.prototype.constructor = BSTree; -BSTree.prototype.getIterator = function () { - return new BSTreeIterator(this) -}; -BSTree.prototype.insert = function (e, t) { - var n = new BSNode(e, t); - var r = this.root; - for (var i = this.root; i;) { - r = i; - if (e < i.key)i = i.left; else i = i.right - } - n.parent = r; - if (!r)this.root = n; else if (e < r.key)r.left = n; else r.right = n -}; -BSTree.prototype.search = function (e, t) { - t = t || this.root; - while (t && e !== t.key)if (e < t.key)t = t.left; else t = t.right; - if (t)return t.item; - return undefined -}; -BSTree.prototype.minimum = function (e) { - e = e || this.root; - while (e && e.left)e = e.left; - return e -}; -BSTree.prototype.maximum = function (e) { - e = e || this.root; - while (e && e.right)e = e.right; - return e -}; -BSTree.prototype.successor = function (e) { - if (e.right)return this.minimum(e.right); - var t = e.parent; - while (t && e === t.right) { - e = t; - t = t.parent - } - return t -}; -BSTree.prototype.predecessor = function (e) { - if (e.left)return this.maximum(e.left); - var t = e.parent; - while (t && e === t.left) { - e = t; - t = t.parent - } - return t -}; -BSTree.prototype.deleteNode = function (e) { - if (!e.left && !e.right) { - if (e === this.root)this.root = null; else if (e.parent.left === e)e.parent.left = null; else e.parent.right = null - } else if (e.left && e.right) { - var t = this.successor(e); - e.key = t.key; - e.item = t.item; - if (t.parent.left === t)t.parent.left = null; else t.parent.right = null - } else { - if (e.right) { - if (e === this.root) { - this.root = e.right; - e.right.parent = null - } else { - e.parent.right = e.right; - e.right.parent = e.parent - } - } else { - if (e === this.root) { - this.root = e.left; - e.left.parent = null - } else { - e.parent.left = e.left; - e.left.parent = e.parent - } - } - } -}; -BSTreeIterator.prototype = new Iterator; -BSTreeIterator.prototype.constructor = BSTreeIterator; -BSTreeIterator.prototype.first = function () { - this.pointer = this.aggregate.minimum() -}; -BSTreeIterator.prototype.next = function () { - this.pointer = this.aggregate.successor(this.pointer) -}; -BSTreeIterator.prototype.last = function () { - this.pointer = this.aggregate.maximum() -}; -BSTreeIterator.prototype.previous = function () { - this.pointer = this.aggregate.predecessor(this.pointer) -}; -BSTreeIterator.prototype.isDone = function () { - return!this.pointer -}; -BSTreeIterator.prototype.getItem = function () { - return this.pointer.item -}; -BSTreeIterator.prototype.getNode = function () { - return this.pointer -}; -BTree.prototype = new Aggregate; -BTree.prototype.constructor = BTree; -BTree.prototype.getIterator = function () { - return new BTreeIterator(this) -}; -BTree.prototype.insert = function (e, t) { - var n = this.root; - if (n.keys.length === 2 * this.t - 1) { - var r = new BNode; - r.childs.push(n); - this.root = r; - this.splitChild(r, 0); - n = r - } - this.size++; - this.insertNonFull(n, e, t) -}; -BTree.prototype.insertNonFull = function (e, t, n) { - while (e) { - var r = e.keys.length - 1; - if (!e.childs.length) { - for (; r > -1 && t < e.keys[r]; r--) { - e.keys[r + 1] = e.keys[r]; - e.items[r + 1] = e.items[r] - } - e.keys[r + 1] = t; - e.items[r + 1] = n; - return - } else { - var i = 0; - r++; - while (i < r) { - var s = Math.floor((i + r) / 2); - if (t <= e.keys[s])r = s; else i = s + 1 - } - if (e.childs[i].keys.length === 2 * this.t - 1) { - this.splitChild(e, i); - if (t > e.keys[i])i++ - } - e = e.childs[i] - } - } -}; -BTree.prototype.search = function (e, t, n) { - t = t || this.root; - n = n || function (t, n) { - return t.keys[n] === e - }; - while (t) { - var r = t.keys.length; - var i = 0, s = r; - while (i < s) { - var o = Math.floor((i + s) / 2); - if (e <= t.keys[o])s = o; else i = o + 1 - } - if (i < r && n(t, i))return t.items[i]; else if (!t.childs.length)return undefined; else t = t.childs[i] - } -}; -BTree.prototype.splitChild = function (e, t) { - var n = new BNode; - var r = e.childs[t]; - for (var i = 0; i < this.t - 1; i++) { - n.keys[i] = r.keys[i + this.t]; - n.items[i] = r.items[i + this.t] - } - if (r.childs.length)for (var s = 0; s < this.t; s++)n.childs[s] = r.childs[s + this.t]; - for (var o = e.keys.length; o > t; o--)e.childs[o + 1] = e.childs[o]; - e.childs[t + 1] = n; - for (var u = e.keys.length - 1; u > t - 1; u--) { - e.keys[u + 1] = e.keys[u]; - e.items[u + 1] = e.items[u] - } - e.keys[t] = r.keys[this.t - 1]; - e.items[t] = r.items[this.t - 1]; - r.keys.splice(r.keys.length - this.t); - r.items.splice(r.items.length - this.t); - r.childs.splice(r.childs.length - this.t) -}; -BTree.prototype.deleteKey = function (e) { - if (this.root.keys.length) { - this.deleteNonMin(this.root, e); - if (!this.root.keys.length && this.root.childs.length)this.root = this.root.childs[0]; - this.size-- - } -}; -BTree.prototype.deleteNonMin = function (e, t) { - var n = 0, r = e.keys.length; - while (n < r) { - var i = Math.floor((n + r) / 2); - if (t <= e.keys[i])r = i; else n = i + 1 - } - if (n < e.keys.length && t === e.keys[n]) { - if (!e.childs.length) { - for (r = n + 1; r < e.keys.length; r++) { - e.keys[r - 1] = e.keys[r]; - e.items[r - 1] = e.items[r] - } - e.keys.pop(); - e.items.pop() - } else { - if (e.childs[n].length === this.t - 1) { - this.augmentChild(e, n); - if (n === e.keys.length + 1)n-- - } - if (e.keys[n] !== t)this.deleteNonMin(e.childs[n], t); else this.deleteMax(e, n) - } - } else { - if (e.childs[n].keys.length === this.t - 1) { - this.augmentChild(e, n); - if (n === e.keys.length + 2)n-- - } - this.deleteNonMin(e.childs[n], t) - } -}; -BTree.prototype.deleteMax = function (e, t) { - var n = e.childs[t]; - var r = true; - while (r) { - if (!n.childs.length) { - e.keys[t] = n.keys[n.keys.length - 1]; - e.items[t] = n.items[n.items.length - 1]; - n.keys.pop(); - n.items.pop(); - r = false - } else { - var i = n.childs[n.keys.length]; - if (i.keys.length === this.t - 1)this.augmentChild(n, n.keys.length); - n = n.childs[n.keys.length] - } - } -}; -BTree.prototype.augmentChild = function (e, t) { - var n = e.childs[t]; - var r; - if (t)r = e.childs[t - 1]; - if (t && r.keys.length > this.t - 1) { - if (n.childs.length) { - for (var i = this.keys.length + 1; i > 0; i--)n.childs[i] = n.childs[i - 1]; - n.childs[0] = r.childs[r.keys.length]; - for (var s = n.keys.length; s > 0; s--) { - n.keys[s] = n.keys[s - 1]; - n.items[s] = n.items[s - 1] - } - n.keys[0] = e.keys[t - 1]; - n.items[0] = e.items[t - 1]; - e.keys[t - 1] = r.keys[r.keys.length - 1]; - e.items[t - 1] = r.items[r.items.length - 1] - } - } else { - if (t < e.keys.length)r = e.childs[t + 1]; - if (t < e.keys.length && r.keys.length > this.t - 1) { - if (r.childs.length) { - n.childs[n.keys.length + 1] = r.childs[0]; - for (var o = 1; o < r.keys.length + 1; o++)r.childs[o - 1] = r.childs[o]; - r.childs.pop() - } - n.keys[n.keys.length] = e.keys[t]; - n.items[n.items.length] = e.items[t]; - e.keys[t] = r.keys[0]; - e.items[t] = r.items[0]; - for (var u = 1; u < r.keys.length; u++) { - r.keys[u - 1] = r.keys[u]; - r.items[u - 1] = r.items[u] - } - r.keys.pop(); - r.items.pop() - } else { - if (t < e.keys.length) { - n.keys[this.t - 1] = e.keys[t]; - n.items[this.t - 1] = e.items[t]; - for (var a = t + 2; a < e.keys.length + 1; a++)e.childs[a - 1] = e.childs[a]; - e.childs.pop(); - for (var f = t + 1; f < e.keys.length; f++) { - e.keys[f - 1] = e.keys[f]; - e.items[f - 1] = e.items[f] - } - e.keys.pop(); - e.items.pop(); - if (r.childs.length)for (var l = 0; l < r.keys.length + 1; l++)n.childs[this.t + l] = r.childs[l]; - for (var c = 0; c < r.keys.length; c++) { - n.keys[c + this.t] = r.keys[c]; - n.items[c + this.t] = r.items[c] - } - } else { - if (r.childs.length)for (var h = 0; h < n.keys.length + 1; h++)r.childs[this.t + h] = n.childs[h]; - r.keys[this.t - 1] = e.keys[e.keys.length - 1]; - r.items[this.t - 1] = e.items[e.keys.length - 1]; - for (var p = 0; p < n.keys.length; p++) { - r.keys[p + this.t] = n.keys[p]; - r.items[p + this.t] = n.items[p] - } - } - } - } -}; -BTree.prototype.contains = function (e, t) { - return this.search(e, null, t) !== undefined -}; -BTree.prototype.fullContains = function (e) { - var t = this.minimumKey(); - while (t !== null && !e(this.search(t)))t = this.successor(t); - return t !== null -}; -BTree.prototype.successor = function (e, t) { - t = t || this.root; - var n = 0, r = t.keys.length; - while (n < r) { - var i = Math.floor((n + r) / 2); - if (e <= t.keys[i])r = i; else n = i + 1 - } - if (t.keys[n] === e)n++; - if (!t.childs.length) { - if (n > t.keys.length - 1)return null; else return t.keys[n] - } - var s = this.successor(e, t.childs[n]); - if (s === null && n < t.keys.length)return t.keys[n]; - return s -}; -BTree.prototype.predecessor = function (e, t) { - t = t || this.root; - var n = 0, r = t.keys.length; - while (n < r) { - var i = Math.floor((n + r) / 2); - if (e <= t.keys[i])r = i; else n = i + 1 - } - n--; - if (!t.childs.length) { - if (n < 0)return null; else return t.keys[n] - } - var s = this.predecessor(e, t.childs[n + 1]); - if (s === null && e > t.keys[0]) { - return t.keys[n] - } - return s -}; -BTree.prototype.minimumKey = function () { - var e = this.root; - while (e.childs.length)e = e.childs[0]; - if (e)return e.keys[0]; - return null -}; -BTree.prototype.maximumKey = function () { - var e = this.root; - while (e.childs.length)e = e.childs[e.childs.length - 1]; - if (e)return e.keys[e.keys.length - 1]; - return null -}; -BTree.prototype.minimum = function () { - var e = this.root; - while (e.childs.length)e = e.childs[0]; - return e.items[0] -}; -BTree.prototype.maximum = function () { - var e = this.root; - while (e.childs.length)e = e.childs[e.childs.length - 1]; - return e.items[e.items.length - 1] -}; -BTree.prototype.getSize = function () { - return this.size -}; -BTree.prototype.isEmpty = function () { - return!this.size -}; -BTree.prototype.execute = function (e) { - var t = arguments[1] || this.root; - for (var n = 0; n < t.items.length; n++)t.items[n] = e(t.items[n]); - for (var r = 0; r < t.childs.length; r++)this.execute(e, t.childs[r]) -}; -BTree.prototype.clear = function () { - this.root = null; - this.size = 0 -}; -BTree.prototype.filter = function (e) { - var t = []; - var n = arguments[1] || this.root; - for (var r = 0; r < n.items.length; r++) { - if (n.childs.length)t = t.concat(this.filter(e, n.childs[r])); - if (e(n.items[r]))t.push(n.items[r]) - } - if (n.childs.length)t = t.concat(this.filter(e, n.childs[n.childs.length - 1])); - return t -}; -BTree.prototype.clone = function () { - var e = new BTree(this.t); - var t = this.getIterator(); - for (t.first(); !t.isDone(); t.next()) { - var n = t.getItem(); - if (n.clone)n = n.clone(); - e.insert(t.getKey(), n) - } - return e -}; -BTree.prototype.cloneDistinct = function () { - var e = new BTree(this.t); - var t = this.getIterator(); - for (t.first(); !t.isDone(); t.next()) { - var n = function (e) { - return e === t.getItem() - }; - if (!e.fullContains(n)) { - if (t.getItem().cloneDistinct)e.insert(t.getKey(), t.getItem().cloneDistinct()); else if (t.getItem().clone)e.insert(t.getKey(), t.getItem().clone()); else e.insert(t.getKey(), t.getItem()) - } - } - return e -}; -BTree.prototype.toArray = function () { - var e = []; - var t = this.getIterator(); - for (t.first(); !t.isDone(); t.next())e.push(t.getItem()); - return e -}; -BTree.prototype.indexOf = function (e, t) { - t = t || function (t) { - return t === e - }; - var n = 0, r = this.minimumKey(); - while (r !== null) { - if (t(this.search(r)))return n; - r = this.successor(r); - n++ - } - return-1 -}; -BTree.prototype.lastIndexOf = function (e, t) { - t = t || function (t) { - return t === e - }; - var n = this.size - 1, r = this.maximumKey(); - while (r !== null) { - if (t(this.search(r)))return n; - n--; - r = this.predecessor(r) - } - return-1 -}; -BTree.prototype.allIndexesOf = function (e, t) { - t = t || function (t) { - return t === e - }; - var n = 0, r = this.minimumKey(); - var i = []; - while (r !== null) { - if (t(this.search(r)))i.push(n); - n++; - r = this.successor(r) - } - return i -}; -BTree.prototype.getItem = function (e) { - if (e < 0 || e > this.size - 1)return undefined; - var t = this.minimum(); - for (var n = 0; n < e; n++)t = this.successor(t); - return this.search(t) -}; -BTreeIterator.prototype = new Iterator; -BTreeIterator.prototype.constructor = BTreeIterator; -BTreeIterator.prototype.first = function () { - this.pointer = this.aggregate.minimumKey() -}; -BTreeIterator.prototype.next = function () { - this.pointer = this.aggregate.successor(this.pointer) -}; -BTreeIterator.prototype.last = function () { - this.pointer = this.aggregate.maximumKey() -}; -BTreeIterator.prototype.previous = function () { - this.pointer = this.aggregate.predecessor(this.pointer) -}; -BTreeIterator.prototype.isDone = function () { - return this.pointer === null -}; -BTreeIterator.prototype.getItem = function () { - return this.aggregate.search(this.pointer) -}; -BTreeIterator.prototype.getKey = function () { - return this.pointer -}; -CircularBufferIterator.prototype = new Iterator; -CircularBufferIterator.prototype.constructor = CircularBufferIterator; -CircularBufferIterator.prototype.first = function () { - this.pointer = this.aggregate.tail; - this.start = true -}; -CircularBufferIterator.prototype.next = function () { - this.pointer = (this.pointer + 1) % this.aggregate.size; - this.start = false -}; -CircularBufferIterator.prototype.last = function () { - this.pointer = (this.aggregate.head - 1) % this.aggregate.size; - this.start = true -}; -CircularBufferIterator.prototype.previous = function () { - this.pointer = (this.pointer - 1) % this.aggregate.size; - this.start = false -}; -CircularBufferIterator.prototype.isDone = function () { - return this.pointer === this.aggregate.head && !this.start || (this.pointer === this.aggregate.tail - 1) % this.aggregate.size || this.aggregate.isEmpty() -}; -CircularBufferIterator.prototype.getItem = function () { - return this.aggregate.read(this.pointer) -}; -CircularBuffer.prototype = new Aggregate; -CircularBuffer.prototype.constructor = CircularBuffer; -CircularBuffer.prototype.getIterator = function () { - return new CircularBufferIterator(this) -}; -CircularBuffer.prototype.write = function (e) { - this.empty = false; - if (this.full)this.tail = (this.tail + 1) % this.size; - this.items[this.head] = e; - this.head = (this.head + 1) % this.size; - if (this.tail === this.head)this.full = true -}; -CircularBuffer.prototype.free = function (e, t) { - if (e < 0)e = 0; - if (e > this.size - 1)e = this.size - 1; - if (t < 0)t = 0; - if (t > this.size - 1)t = this.size - 1; - for (var n = e; n < t; n = (n + 1) % this.size)delete this.items[n]; - if (this.tail > e - 1 || this.tail < t)if (this.tail < this.head) { - this.tail = (e - 1) % this.size - } else { - this.tail = t - } - if (this.head > e || this.head < t)if (this.tail < this.head) { - this.head = t - } else { - this.head = e - } - if (e !== t)this.full = false; - for (var r = 0; r < this.size; r++)if (this.items[r] !== undefined) { - this.empty = false; - return - } - this.empty = true -}; -CircularBuffer.prototype.freeAll = function () { - for (var e = 0; e < this.size; e++)delete this.items[e]; - this.empty = true; - this.head = 0; - this.tail = 0 -}; -CircularBuffer.prototype.read = function (e) { - return this.items[e % this.size] -}; -CircularBuffer.prototype.isEmpty = function () { - return this.empty -}; -CircularBuffer.prototype.isFull = function () { - return this.full -}; -CircularBuffer.prototype.clone = function () { - var e = new CircularBuffer(this.size); - e.head = this.head; - e.tail = this.tail; - for (var t = 0; t < this.items.length; t++)e.items[t] = this.items[t]; - e.empty = this.empty; - e.full = this.full; - return e -}; -CircularBuffer.prototype.resize = function (e) { - if (this.size < e) { - if (this.head < this.tail + 1) { - for (var t = 0; t < this.head; t++) { - this.items[(t + this.size) % e] = this.items[t]; - delete this.items[t] - } - this.head = (this.head + this.size) % e - } - } else if (this.size > e) { - if (this.head < this.tail + 1) { - var n = e; - if (this.tail > e - 1) { - n = this.tail; - this.tail = 0 - } - var r = this.size - n; - for (var i = this.head - r - 1; i > n - 1 || i < this.head - r; i--) { - this.items[(i + r) % this.size] = this.items[i]; - if (!i)i = this.size - } - this.head = (this.head + r) % this.size - } - } - this.size = e -}; -DoubleLinkedList.prototype = new Aggregate; -DoubleLinkedList.prototype.constructor = DoubleLinkedList; -DoubleLinkedList.prototype.getIterator = function () { - return new DoubleLinkedListIterator(this) -}; -DoubleLinkedList.prototype.pushFront = function (e) { - var t = new DLLNode(e); - t.next = this.first; - this.first = t; - if (t.next)t.next.previous = t; else this.last = t; - this.length++ -}; -DoubleLinkedList.prototype.pushBack = function (e) { - var t = new DLLNode(e); - t.previous = this.last; - this.last = t; - if (t.previous)t.previous.next = t; else this.first = t; - this.length++ -}; -DoubleLinkedList.prototype.popFront = function () { - if (this.length) { - var e = this.first; - this.first = e.next; - if (e.next)e.next.previous = null; - this.length--; - e.next = null; - return e.item - } - return undefined -}; -DoubleLinkedList.prototype.popBack = function () { - if (this.length) { - var e = this.last; - this.last = e.previous; - if (e.previous)e.previous.next = null; - this.length--; - e.previous = null; - return e.item - } - return undefined -}; -DoubleLinkedList.prototype.multiPopFront = function (e) { - var t = []; - for (var n = 0; n < e && this.length; n++)t.push(this.popFront()); - return t -}; -DoubleLinkedList.prototype.multiPopBack = function (e) { - var t = []; - for (var n = 0; n < e && this.length; n++)t.push(this.popBack()); - return t -}; -DoubleLinkedList.prototype.peek = function () { - if (!this.length)return undefined; - return this.first.item -}; -DoubleLinkedList.prototype.addAt = function (e, t) { - if (t < 0)return; - if (!t) { - this.pushFront(e); - return - } - if (t === this.length) { - this.pushBack(e); - return - } - var n = this.first; - if (!n && t > 0)this.pushBack(undefined); - for (var r = 0; r < t - 1; r++, n = n.next) { - if (n === this.last)this.pushBack(undefined) - } - if (n === this.last)this.pushBack(e); else if (n === this.first)this.pushFront(e); else { - var i = new DLLNode(e); - i.next = n.next; - i.previous = n; - n.next = i; - if (i.next)i.next.previous = i; - this.length++ - } -}; -DoubleLinkedList.prototype.removeAt = function (e) { - if (e < 0 || e > this.length - 1)return undefined; - if (e === 0)return this.popFront(); - if (e === this.length - 1)return this.popBack(); - var t = this.first; - for (; e > 0; e--)t = t.next; - t.previous.next = t.next; - t.next.previous = t.previous; - t.next = null; - t.previous = null; - this.length--; - return t.item -}; -DoubleLinkedList.prototype.remove = function (e, t) { - t = t || function (t) { - return t === e - }; - var n = this.first; - var r = null; - while (n) { - if (t(n.item)) { - if (n === this.first)this.first = n.next; - if (n === this.last)this.last = r; - if (r) { - r.next = n.next; - if (n.next)n.next.previous = r - } - return - } - r = n; - n = n.next - } -}; -DoubleLinkedList.prototype.removeAll = function (e, t) { - t = t || function (t) { - return t === e - }; - var n = this.first; - var r = null; - while (n) { - if (t(n.item)) { - if (n === this.first)this.first = n.next; - if (n === this.last)this.last = r; - if (r) { - r.next = n.next; - if (n.next)n.next.previous = r - } - } else r = n; - n = n.next - } -}; -DoubleLinkedList.prototype.removeSegment = function (e, t) { - var n = []; - if (t > -1 && e < this.length) { - if (e === 0)return this.multiPopFront(t + 1); - if (t === this.length - 1 || e > t)return this.multiPopBack(Math.max(t - e, this.length - e)).reverse(); - var r = this.first; - for (var i = 0; i < e - 1; i++)r = r.next; - var s = r.next; - for (var o = e; o < t + 1 && o < this.length; o++) { - n.push(s.item); - s = s.next - } - this.length -= Math.min(t - e + 1, this.length - e); - r.next = s; - s.previous = r - } - return n -}; -DoubleLinkedList.prototype.modifyAt = function (e, t) { - var n = this.getNode(e); - if (n)n.item = t -}; -DoubleLinkedList.prototype.clear = function () { - this.first = null; - this.last = null; - this.length = 0 -}; -DoubleLinkedList.prototype.contains = function (e, t) { - t = t || function (t) { - return t === e - }; - var n = 0; - var r = this.first; - while (n < this.length && !t(r.item)) { - n++; - r = r.next - } - return n < this.length -}; -DoubleLinkedList.prototype.execute = function (e) { - var t = this.first; - while (t) { - t.item = e(t.item); - t = t.next - } -}; -DoubleLinkedList.prototype.deleteNode = function (e) { - if (e === this.first) { - this.popFront(); - return - } - if (e === this.last) { - this.popBack(); - return - } - e.previous.next = e.next; - e.next.previous = e.previous; - this.length-- -}; -DoubleLinkedList.prototype.getNode = function (e, t) { - if (e < 0 || e > this.length - 1)return undefined; - var n = Math.floor(this.length / 2); - if (e < n || t) { - t = t || this.first; - for (; e > 0; e--)t = t.next - } else for (e = this.length - e - 1, t = this.last; e > 0; e--)t = t.previous; - return t -}; -DoubleLinkedList.prototype.getItem = function (e) { - if (e < 0 || e > this.length - 1)return undefined; - var t; - var n = Math.floor(this.length / 2); - if (e < n)for (t = this.first; e > 0; e--)t = t.next; else for (e = this.length - e - 1, t = this.last; e > 0; e--)t = t.previous; - return t.item -}; -DoubleLinkedList.prototype.parallelSort = function () { - function n(r, i, s) { - if (r < i) { - var o = Math.floor((r + i) / 2); - var u = new Worker("DoubleLinkedList/WorkerSort.js"); - var a = new Worker("DoubleLinkedList/WorkerSort.js"); - e.push(u); - e.push(a); - var f = e.length; - u.postMessage({cmd: "start", from: r, to: o, worker: s}); - a.postMessage({cmd: "start", from: o + 1, to: i, worker: s}); - n(r, o, f - 2); - n(o + 1, i, f - 1); - u.onmessage = function (n) { - var r = n.data; - switch (r.cmd) { - case"finished": - e[r.worker].postMessage({cmd: "finished", array: t}); - break; - case"replace": - t[r.index] = r.value; - break - } - }; - a.onmessage = function (n) { - var r = n.data; - switch (r.cmd) { - case"finished": - e[r.worker].postMessage({cmd: "finished", array: t}); - break; - case"replace": - t[r.index] = r.value; - break - } - } - } - } - - var e = []; - var t = this.toArray(); - console.log(t); - var r = this; - var i = new Worker("DoubleLinkedList/WorkerSort.js"); - e.push(i); - i.postMessage({cmd: "start", from: 0, to: this.length - 1, worker: -1, array: t}); - i.onmessage = function (e) { - var n = e.data; - switch (n.cmd) { - case"finished": - r.fromArray(t); - console.log(r); - break; - case"replace": - t[n.index] = n.value - } - }; - n(0, this.length - 1, 0) -}; -DoubleLinkedList.prototype.sort = function (e) { - function n(e, i, s, o) { - if (e < i) { - var u = Math.floor((e + i) / 2); - var a = t.getNode(u - e, s); - n(e, u, s, a); - n(u + 1, i, a.next, o); - r(e, u, i, s) - } - } - - function r(t, n, r, i) { - var s = []; - var o = []; - var u = i; - for (var a = 0; a < n - t + 1; a++, u = u.next)s[a] = u.item; - for (var f = 0; f < r - n; f++, u = u.next)o[f] = u.item; - var l = 0, c = 0; - for (var h = t; h < r + 1; h++, i = i.next) { - if (c > r - n - 1 || e(s[l]) <= e(o[c]) && l < n - t + 1) { - i.item = s[l]; - l++ - } else { - i.item = o[c]; - c++ - } - } - } - - if (!e)e = function (e) { - return e - }; - var t = this; - n(0, this.length - 1, this.first, this.last) -}; -DoubleLinkedList.prototype.toArray = function () { - var e = []; - for (var t = this.first, n = 0; t; t = t.next, n++)e[n] = t.item; - return e -}; -DoubleLinkedList.prototype.getLength = function () { - return this.length -}; -DoubleLinkedList.prototype.fromArray = function (e) { - var t = this.first; - for (var n = 0; n < Math.min(this.length, e.length); n++, t = t.next)t.item = e[n]; - if (this.length < e.length)for (var r = this.length; r < e.length; r++)this.pushBack(e[r]); else for (var i = e.length; i < this.length;)this.popBack() -}; -DoubleLinkedList.prototype.filter = function (e) { - var t = []; - for (var n = this.first; n; n = n.next) { - if (e(n.item))t.push(n.item) - } - return t -}; -DoubleLinkedList.prototype.reverse = function () { - for (var e = this.first, t = this.last; e !== t && e.previous !== t; e = e.next, t = t.previous) { - var n = e.item; - e.item = t.item; - t.item = n - } -}; -DoubleLinkedList.prototype.isEmpty = function () { - return!this.length -}; -DoubleLinkedList.prototype.indexOf = function (e, t) { - t = t || function (t) { - return t === e - }; - var n = 0; - var r = this.first; - while (r) { - if (t(r.item))return n; - n++; - r = r.next - } - return-1 -}; -DoubleLinkedList.prototype.lastIndexOf = function (e, t) { - t = t || function (t) { - return t === e - }; - var n = this.length - 1; - var r = this.last; - while (r) { - if (t(r.item))return n; - n--; - r = r.previous - } - return-1 -}; -DoubleLinkedList.prototype.allIndexesOf = function (e, t) { - t = t || function (t) { - return t === e - }; - var n = 0; - var r = this.first; - var i = []; - while (r) { - if (t(r.item))i.push(n); - n++; - r = r.next - } - return i -}; -DoubleLinkedList.prototype.join = function (e) { - if (this.last)this.last.next = e.first; else this.first = e.first; - if (e.first)e.first.previous = this.last; - this.last = e.last; - this.length += e.length -}; -DoubleLinkedList.prototype.divide = function (e) { - var t = new DoubleLinkedList; - if (e > -1 && e < this.length) { - var n = this.first; - var r = null; - for (var i = 0; i < e; i++) { - r = n; - n = n.next - } - if (n === this.first) { - t.first = this.first; - t.last = this.last; - this.first = null; - this.last = null - } else { - t.first = n; - t.last = this.last; - this.last = r; - r.next = null; - n.previous = null - } - t.length = this.length - e; - this.length = e - } - return t -}; -DoubleLinkedList.prototype.clone = function () { - var e = new DoubleLinkedList; - var t = this.first; - for (var n = 0; n < this.length; n++, t = t.next)if (t.item.clone)e.pushBack(t.item.clone()); else e.pushBack(t.item); - return e -}; -DoubleLinkedList.prototype.cloneDistinct = function () { - var e = new DoubleLinkedList; - var t = this.first; - for (var n = 0; n < this.length; n++, t = t.next)if (!e.contains(t.item))if (t.item.cloneDistinct)e.pushBack(t.item.cloneDistinct()); else if (t.item.clone)e.pushBack(t.item.clone()); else e.pushBack(t.item); - return e -}; -DoubleLinkedList.prototype.split = function (e) { - var t = this.length; - var n = [this]; - for (var r = e; r < t; r += e)n.push(n[n.length - 1].divide(e)); - return n -}; -DoubleLinkedList.prototype.count = function (e) { - var t = 0; - var n = this.first; - while (n) { - if (e(n.item))t++; - n = n.next - } - return t -}; -DoubleLinkedListIterator.prototype = new Iterator; -DoubleLinkedListIterator.prototype.constructor = DoubleLinkedListIterator; -DoubleLinkedListIterator.prototype.first = function () { - this.pointer = this.aggregate.first -}; -DoubleLinkedListIterator.prototype.next = function () { - this.pointer = this.pointer.next -}; -DoubleLinkedListIterator.prototype.last = function () { - this.pointer = this.aggregate.last -}; -DoubleLinkedListIterator.prototype.previous = function () { - this.pointer = this.pointer.previous -}; -DoubleLinkedListIterator.prototype.isDone = function () { - return!this.pointer -}; -DoubleLinkedListIterator.prototype.getItem = function () { - return this.pointer.item -}; -DoubleLinkedListIterator.prototype.getNode = function () { - return this.pointer -}; -onmessage = function (e) { - var t = e.data; - switch (t.cmd) { - case"start": - this.finished = 0; - this.from = t.from; - this.to = t.to; - this.worker = t.worker; - if (this.from === this.to) { - this.postMessage({cmd: "finished", worker: this.worker}); - close() - } - break; - case"finished": - this.finished++; - if (this.finished > 1) { - this.array = t.array; - merge(this.from, this.to, this.array); - this.postMessage({cmd: "finished", worker: this.worker}); - close() - } - break; - default: - this.postMessage("Something went wrong") - } -}; -HashTable.prototype.insert = function (e, t) { - this.keyLength++; - this.items[this.hash(e)].pushBack({key: e, item: t}) -}; -HashTable.prototype.deleteKey = function (e) { - var t = this.items[this.hash(e)]; - var n = t.getIterator(); - for (n.first(); !n.isDone() && n.getItem().key !== e;)n.next(); - if (!n.isDone()) { - t.deleteNode(n.getNode()); - this.keyLength-- - } -}; -HashTable.prototype.deleteAllKey = function (e) { - var t = this.items[this.hash(e)]; - var n = t.getIterator(); - var r = 0; - for (n.first(); !n.isDone(); n.next())if (n.getItem().key === e) { - t.deleteNode(n.getNode()); - r++ - } - this.keyLength -= r -}; -HashTable.prototype.search = function (e) { - var t = this.items[this.hash(e)]; - var n = t.getIterator(); - for (n.first(); !n.isDone(); n.next())if (n.getItem().key === e)return n.getItem().item; - return undefined -}; -HashTable.prototype.containsKey = function (e, t) { - t = t || function (t) { - return t === e - }; - var n = this.items[this.hash(e)]; - var r = n.getIterator(); - for (r.first(); !r.isDone(); r.next())if (t(r.getItem().key))return true; - return false -}; -HashTable.prototype.searchAll = function (e) { - var t = this.items[this.hash(e)]; - var n = t.getIterator(); - var r = []; - for (n.first(); !n.isDone(); n.next())if (n.getItem().key === e)r.push(n.getItem().item); - return r -}; -HashTable.prototype.getKeys = function () { - var e = []; - for (var t = 0; t < this.size; t++) { - var n = this.items[t].getIterator(); - for (n.first(); !n.isDone(); n.next())e.push(n.getItem().key) - } - return e -}; -HashTable.prototype.getItems = function () { - var e = []; - for (var t = 0; t < this.size; t++) { - var n = this.items[t].getIterator(); - for (n.first(); !n.isDone(); n.next())e.push(n.getItem().item) - } - return e -}; -HashTable.prototype.clear = function () { - this.items = []; - for (var e = 0; e < this.size; e++)this.items[e] = new DoubleLinkedList; - this.keyLength = 0 -}; -HashTable.prototype.getNumberOfKeys = function () { - return this.keyLength -}; -HashTable.prototype.isEmpty = function () { - return!this.keyLength -}; -HashTable.prototype.execute = function (e) { - for (var t = 0; t < this.size; t++)this.items[t].execute(e) -}; -HashTable.prototype.filter = function (e) { - var t = []; - for (var n = 0; n < this.size; n++)t.concat(this.items[n].filter(e)); - return t -}; -HashTable.prototype.getSize = function () { - return this.size -}; -HashTable.prototype.clone = function () { - var e = new HashTable(this.size); - for (var t = 0; t < this.size; t++)for (var n = this.items[t].first; n; n = n.next)e.insert(n.key, n.item); - return e -}; -LinkedList.prototype = new Aggregate; -LinkedList.prototype.constructor = LinkedList; -LinkedList.prototype.getIterator = function () { - return new LinkedListIterator(this) -}; -LinkedList.prototype.pushFront = function (e) { - var t = new LLNode(e); - t.next = this.first; - this.first = t; - if (!this.last)this.last = t; - this.length++ -}; -LinkedList.prototype.pushBack = function (e) { - var t = new LLNode(e); - if (this.last)this.last.next = t; else this.first = t; - this.last = t; - this.length++ -}; -LinkedList.prototype.popFront = function () { - if (this.length) { - var e = this.first; - this.first = this.first.next; - this.length--; - e.next = null; - return e.item - } - return undefined -}; -LinkedList.prototype.popBack = function () { - if (this.length) { - var e = this.last; - var t = this.first; - while (t.next && t.next.next) { - t = t.next - } - if (e === t)this.last = null; else this.last = t; - t.next = null; - this.length--; - return e.item - } - return undefined -}; -LinkedList.prototype.multiPopFront = function (e) { - var t = []; - for (var n = 0; n < e && this.length; n++)t.push(this.popFront()); - return t -}; -LinkedList.prototype.multiPopBack = function (e) { - var t = []; - for (var n = 0; n < e && this.length; n++)t.push(this.popBack()); - return t -}; -LinkedList.prototype.peek = function () { - if (!this.length)return undefined; - return this.first.item -}; -LinkedList.prototype.addAt = function (e, t) { - if (t < 0)return; - if (!t) { - this.pushFront(e); - return - } - if (t === this.length) { - this.pushBack(e); - return - } - var n = this.first; - if (!n && t > 0)this.pushBack(undefined); - for (var r = 0; r < t - 1; r++, n = n.next) { - if (n === this.last)this.pushBack(undefined) - } - if (n === this.last)this.pushBack(e); else if (n === this.first)this.pushFront(e); else { - var i = new LLNode(e); - i.next = n.next; - n.next = i; - this.length++ - } -}; -LinkedList.prototype.removeAt = function (e) { - if (e < 0 || e > this.length - 1)return undefined; - if (e === 0)return this.popFront(); - if (e === this.length - 1)return this.popBack(); - var t = this.first; - for (; e > 1; e--)t = t.next; - var n = t.next; - t.next = n.next; - this.length--; - return n.item -}; -LinkedList.prototype.remove = function (e, t) { - t = t || function (t) { - return t === e - }; - var n = this.first; - var r = null; - while (n) { - if (t(n.item)) { - if (n === this.first)this.first = n.next; - if (n === this.last)this.last = r; - if (r)r.next = n.next; - return - } - r = n; - n = n.next - } -}; -LinkedList.prototype.removeAll = function (e, t) { - t = t || function (t) { - return t === e - }; - var n = this.first; - var r = null; - while (n) { - if (t(n.item)) { - if (n === this.first)this.first = n.next; - if (n === this.last)this.last = r; - if (r)r.next = n.next - } else r = n; - n = n.next - } -}; -LinkedList.prototype.removeSegment = function (e, t) { - var n = []; - if (t > -1 && e < this.length) { - if (e === 0)return this.multiPopFront(t + 1); - if (t === this.length - 1 || e > t)return this.multiPopBack(Math.max(t - e, this.length - e)).reverse(); - var r = this.first; - for (var i = 0; i < e - 1; i++)r = r.next; - var s = r.next; - for (var o = e; o < t + 1 && o < this.length; o++) { - n.push(s.item); - s = s.next - } - this.length -= Math.min(t - e + 1, this.length - e); - r.next = s - } - return n -}; -LinkedList.prototype.modifyAt = function (e, t) { - var n = this.getNode(e); - if (n)n.item = t -}; -LinkedList.prototype.clear = function () { - this.first = null; - this.last = null; - this.length = 0 -}; -LinkedList.prototype.contains = function (e, t) { - t = t || function (t) { - return t === e - }; - var n = 0; - var r = this.first; - while (n < this.length && !t(r.item)) { - n++; - r = r.next - } - return n < this.length -}; -LinkedList.prototype.execute = function (e) { - var t = this.first; - while (t) { - t.item = e(t.item); - t = t.next - } -}; -LinkedList.prototype.getNode = function (e) { - if (e < 0 || e > this.length - 1)return undefined; - var t = this.first; - for (; e > 0; e--)t = t.next; - return t -}; -LinkedList.prototype.getItem = function (e) { - if (e < 0 || e > this.length - 1)return undefined; - var t = this.first; - for (; e > 0; e--)t = t.next; - return t.item -}; -LinkedList.prototype.toArray = function () { - var e = []; - for (var t = this.first, n = 0; t; t = t.next, n++)e[n] = t.item; - return e -}; -LinkedList.prototype.getLength = function () { - return this.length -}; -LinkedList.prototype.fromArray = function (e) { - var t = this.first; - for (var n = 0; n < Math.min(this.length, e.length); n++, t = t.next)t.item = e[n]; - if (this.length < e.length)for (var r = this.length; r < e.length; r++)this.pushBack(e[r]); else for (var i = e.length; i < this.length;)this.popBack() -}; -LinkedList.prototype.filter = function (e) { - var t = []; - for (var n = this.first; n; n = n.next) { - if (e(n.item))t.push(n.item) - } - return t -}; -LinkedList.prototype.isEmpty = function () { - return!this.length -}; -LinkedList.prototype.indexOf = function (e, t) { - t = t || function (t) { - return t === e - }; - var n = 0; - var r = this.first; - while (r) { - if (t(r.item))return n; - n++; - r = r.next - } - return-1 -}; -LinkedList.prototype.lastIndexOf = function (e, t) { - t = t || function (t) { - return t === e - }; - var n = 0; - var r = this.first; - var i = -1; - while (r) { - if (t(r.item))i = n; - n++; - r = r.next - } - return i -}; -LinkedList.prototype.allIndexesOf = function (e, t) { - t = t || function (t) { - return t === e - }; - var n = 0; - var r = this.first; - var i = []; - while (r) { - if (t(r.item))i.push(n); - n++; - r = r.next - } - return i -}; -LinkedList.prototype.join = function (e) { - if (this.last)this.last.next = e.first; else this.first = e.first; - this.last = e.last; - this.length += e.length -}; -LinkedList.prototype.divide = function (e) { - var t = new LinkedList; - if (e > -1 && e < this.length) { - var n = this.first; - var r = null; - for (var i = 0; i < e; i++) { - r = n; - n = n.next - } - if (n === this.first) { - t.first = this.first; - t.last = this.last; - this.first = null; - this.last = null - } else { - t.first = n; - t.last = this.last; - this.last = r; - r.next = null - } - t.length = this.length - e; - this.length = e - } - return t -}; -LinkedList.prototype.clone = function () { - var e = new LinkedList; - var t = this.first; - for (var n = 0; n < this.length; n++, t = t.next)if (t.item.clone)e.pushBack(t.item.clone()); else e.pushBack(t.item); - return e -}; -LinkedList.prototype.cloneDistinct = function () { - var e = new LinkedList; - var t = this.first; - for (var n = 0; n < this.length; n++, t = t.next)if (!e.contains(t.item))if (t.item.cloneDistinct)e.pushBack(t.item.cloneDistinct()); else if (t.item.clone)e.pushBack(t.item.clone()); else e.pushBack(t.item); - return e -}; -LinkedList.prototype.split = function (e) { - var t = this.length; - var n = [this]; - for (var r = e; r < t; r += e)n.push(n[n.length - 1].divide(e)); - return n -}; -LinkedList.prototype.count = function (e) { - var t = 0; - var n = this.first; - while (n) { - if (e(n.item))t++; - n = n.next - } - return t -}; -LinkedListIterator.prototype = new Iterator; -LinkedListIterator.prototype.constructor = LinkedListIterator; -LinkedListIterator.prototype.first = function () { - this.pointer = this.aggregate.first -}; -LinkedListIterator.prototype.next = function () { - this.pointer = this.pointer.next -}; -LinkedListIterator.prototype.last = function () { - this.pointer = this.aggregate.last -}; -LinkedListIterator.prototype.previous = function () { - var e = this.pointer; - for (this.pointer = this.first(); this.pointer.next !== e;)this.next() -}; -LinkedListIterator.prototype.isDone = function () { - return!this.pointer -}; -LinkedListIterator.prototype.getItem = function () { - return this.pointer.item -}; -LinkedListIterator.prototype.getNode = function () { - return this.pointer -}; -PriorityQueue.prototype = new Aggregate; -PriorityQueue.prototype.constructor = PriorityQueue; -PriorityQueue.prototype.getIterator = function () { - return new PriorityQueueIterator(this) -}; -PriorityQueue.prototype.enqueue = function (e, t) { - var n = this.items.search(e); - if (!n) { - n = new Queue; - this.items.insert(e, n) - } - n.enqueue(t); - this.length++ -}; -PriorityQueue.prototype.multiEnqueue = function (e, t) { - for (var n = 0; n < t.length; n++)this.enqueue(e, t[n]) -}; -PriorityQueue.prototype.dequeue = function () { - var e = this.items.maximum(); - var t = undefined; - if (e) { - var n = e.item; - t = n.dequeue(); - if (n.isEmpty())this.items.deleteNode(e); - this.length-- - } - return t -}; -PriorityQueue.prototype.multiDequeue = function (e) { - var t = []; - for (var n = 0; n < e && this.length; n++)t.push(this.dequeue()); - return t -}; -PriorityQueue.prototype.remove = function (e, t) { - t = t || 1; - var n = this.items.getIterator(); - for (n.last(); !n.isDone() && t > 0; n.previous()) { - var r = n.getItem(); - if (e > -1 && e < r.getLength()) { - var i = r.getLength(); - r.remove(e, t); - t -= i - e; - e = 0; - if (!r.getLength())this.items.deleteNode(n.getNode()) - } else e = e - r.getLength() - } -}; -PriorityQueue.prototype.getItem = function (e) { - var t = this.items.getIterator(); - for (t.last(); !t.isDone(); t.previous()) { - var n = t.getItem(); - if (e > -1 && e < n.getLength())return n.getItem(e); - e = e - n.getLength() - } - return undefined -}; -PriorityQueue.prototype.getItems = function (e) { - var t = this.items.search(e); - if (t)return t.items; - return[] -}; -PriorityQueue.prototype.peek = function () { - return this.items.maximum().item.peek() -}; -PriorityQueue.prototype.getLength = function () { - return this.length -}; -PriorityQueue.prototype.isEmpty = function () { - return!this.length -}; -PriorityQueue.prototype.clear = function () { - this.items = new RBTreeList; - this.length = 0 -}; -PriorityQueue.prototype.containsPriority = function (e, t) { - if (t)return this.items.fullContains(t); else return this.items.contains(e) -}; -PriorityQueue.prototype.toQueue = function () { - var e = new Queue; - var t = this.items.getIterator(); - for (t.last(); !t.isDone(); t.previous()) { - var n = t.getItem(); - var r = n.getIterator(); - for (r.first(); !r.isDone(); r.next())e.enqueue(r.getItem()) - } - return e -}; -PriorityQueue.prototype.execute = function (e) { - var t = this.items.getIterator(); - for (t.last(); !t.isDone(); t.previous())t.getItem().execute(e) -}; -PriorityQueue.prototype.changePriority = function (e, t) { - var n = this.getItem(e); - this.remove(e); - this.enqueue(t, n) -}; -PriorityQueue.prototype.filter = function (e) { - var t = []; - var n = this.items.getIterator(); - for (n.last(); !n.isDone(); n.previous()) { - var r = n.getItem().getIterator(); - for (r.first(); !r.isDone(); r.next()) { - if (e(r.getItem()))t.push(r.getItem()) - } - } - return t -}; -PriorityQueue.prototype.clone = function () { - var e = new PriorityQueue; - e.items = this.items.clone(); - e.length = this.length; - return e -}; -PriorityQueue.prototype.cloneDistinct = function () { - var e = new PriorityQueue; - e.items = this.items.cloneDistinct(); - e.length = e.items.getSize(); - return e -}; -PriorityQueueIterator.prototype = new Iterator; -PriorityQueueIterator.prototype.constructor = PriorityQueueIterator; -PriorityQueueIterator.prototype.first = function () { - this.pointerNode = this.aggregate.items.maximum(); - this.pointerPosition = 0 -}; -PriorityQueueIterator.prototype.next = function () { - this.pointerPosition++; - if (this.pointerPosition > this.pointerNode.item.getLength() - 1) { - this.pointerNode = this.pointerNode.previous; - this.pointerPosition = 0 - } -}; -PriorityQueueIterator.prototype.last = function () { - this.pointerNode = this.aggregate.items.minimum(); - this.pointerPosition = this.pointerNode.item.getLength() - 1 -}; -PriorityQueueIterator.prototype.previous = function () { - this.pointerPosition--; - if (this.pointerPosition < 0) { - this.pointerNode = this.pointerNode.next; - if (this.pointerNode)this.pointerPosition = this.pointerNode.item.getLength() - 1 - } -}; -PriorityQueueIterator.prototype.isDone = function () { - return!this.pointerNode -}; -PriorityQueueIterator.prototype.getItem = function () { - return this.pointerNode.item.items[this.pointerPosition] -}; -Queue.prototype = new Aggregate; -Queue.prototype.constructor = Queue; -Queue.prototype.getIterator = function () { - return new QueueIterator(this) -}; -Queue.prototype.enqueue = function (e) { - this.items.push(e) -}; -Queue.prototype.multiEnqueue = function (e) { - for (var t = 0; t < e.length; t++)this.items.push(e[t]) -}; -Queue.prototype.dequeue = function () { - if (!this.items.length)return undefined; - return this.items.splice(0, 1)[0] -}; -Queue.prototype.multiDequeue = function (e) { - return this.items.splice(0, e) -}; -Queue.prototype.remove = function (e, t) { - t = t || 1; - this.items.splice(e, t) -}; -Queue.prototype.getItem = function (e) { - if (e < 0 || e > this.items.length - 1)return undefined; - return this.items[e] -}; -Queue.prototype.peek = function () { - if (this.items.length)return this.items[0]; - return undefined -}; -Queue.prototype.clear = function () { - this.items = [] -}; -Queue.prototype.contains = function (e, t) { - t = t || function (t) { - return t === e - }; - var n = 0; - while (n < this.items.length && !t(this.items[n]))n++; - return n < this.items.length -}; -Queue.prototype.execute = function (e) { - for (var t = 0; t < this.items.length; t++)this.items[t] = e(this.items[t]) -}; -Queue.prototype.getLength = function () { - return this.items.length -}; -Queue.prototype.isEmpty = function () { - return!this.items.length -}; -Queue.prototype.filter = function (e) { - var t = []; - for (var n = 0; n < this.items.length; n++)if (e(this.items[n]))t.push(this.items[n]); - return t -}; -Queue.prototype.indexOf = function (e, t) { - t = t || function (t) { - return t === e - }; - var n = 0; - while (n < this.items.length) { - if (t(this.items[n]))return n; - n++ - } - return-1 -}; -Queue.prototype.lastIndexOf = function (e, t) { - t = t || function (t) { - return t === e - }; - var n = this.items.length - 1; - while (n > -1) { - if (t(this.items[n]))return n; - n-- - } - return-1 -}; -Queue.prototype.allIndexesOf = function (e, t) { - t = t || function (t) { - return t === e - }; - var n = 0; - var r = []; - while (n < this.items.length) { - if (t(this.items[n]))r.push(n); - n++ - } - return r -}; -Queue.prototype.clone = function () { - var e = new Queue; - for (var t = 0; t < this.items.length; t++)if (this.items[t].clone)e.enqueue(this.items[t].clone()); else e.enqueue(this.items[t]); - return e -}; -Queue.prototype.cloneDistinct = function () { - var e = new Queue; - for (var t = 0; t < this.items.length; t++)if (!e.contains(this.items[t]))if (this.items[t].cloneDistinct)e.enqueue(this.items[t].cloneDistinct()); else if (this.items[t].clone)e.enqueue(this.items[t].clone()); else e.enqueue(this.items[t]); - return e -}; -QueueIterator.prototype = new Iterator; -QueueIterator.prototype.constructor = QueueIterator; -QueueIterator.prototype.first = function () { - this.pointer = 0 -}; -QueueIterator.prototype.next = function () { - this.pointer++ -}; -QueueIterator.prototype.last = function () { - this.pointer = this.aggregate.items.length - 1 -}; -QueueIterator.prototype.previous = function () { - this.pointer-- -}; -QueueIterator.prototype.isDone = function () { - return this.pointer < 0 || this.pointer > this.aggregate.items.length - 1 -}; -QueueIterator.prototype.getItem = function () { - return this.aggregate.getItem(this.pointer) -}; -RBTree.prototype = new Aggregate; -RBTree.prototype.constructor = RBTree; -RBTree.prototype.getIterator = function () { - return new RBTreeIterator(this) -}; -RBTree.prototype.insert = function (e, t) { - var n = new RBNode(e, t); - this.size++; - if (!this.root) { - this.root = n; - n.type = "b"; - return - } - var r = this.root; - for (var i = this.root; i;) { - r = i; - if (e < i.key)i = i.left; else i = i.right - } - n.parent = r; - if (!r)this.root = n; else if (e < r.key)r.left = n; else r.right = n; - this.insertFixUp(n) -}; -RBTree.prototype.insertFixUp = function (e) { - for (var t = e.parent; t && t.type === "r"; t = e.parent) { - if (t === t.parent.left) { - var n = t.parent.right; - if (n && n.type === "r") { - t.type = "b"; - n.type = "b"; - t.parent.type = "r"; - e = t.parent - } else if (e === t.right) { - e = t; - this.leftRotate(e) - } else { - t.type = "b"; - t.parent.type = "r"; - this.rightRotate(t.parent) - } - } else { - var n = t.parent.left; - if (n && n.type === "r") { - t.type = "b"; - n.type = "b"; - t.parent.type = "r"; - e = t.parent - } else if (e === t.left) { - e = t; - this.rightRotate(e) - } else { - t.type = "b"; - t.parent.type = "r"; - this.leftRotate(t.parent) - } - } - } - this.root.type = "b" -}; -RBTree.prototype.deleteNode = function (e) { - var t; - this.size--; - if (!e.left || !e.right)t = e; else { - t = this.successor(e); - e.key = t.key; - e.item = t.item - } - var n; - if (!t.left)n = t.right; else n = t.left; - if (n)n.parent = t.parent; - if (!t.parent)this.root = n; else if (t === t.parent.left)t.parent.left = n; else t.parent.right = n; - if (t.type === "b")this.deleteFixUp(n, t.parent) -}; -RBTree.prototype.deleteFixUp = function (e, t) { - while (e !== this.root && (!e || e.type === "b")) { - if (e === t.left) { - var n = t.right; - if (n && n.type === "r") { - n.type = "b"; - t.type = "r"; - this.leftRotate(t); - n = t.right - } - if (n && (!n.left || n.left.type === "b") && (!n.right || n.right.type === "b")) { - n.type = "r"; - e = t - } else { - if (!n.right || n.right.type === "b") { - n.left.type = "b"; - n.type = "r"; - this.rightRotate(n); - n = t.right - } - n.type = t.type; - t.type = "b"; - n.right.type = "b"; - this.leftRotate(t); - e = this.root - } - } else { - var n = t.left; - if (n && n.type === "r") { - n.type = "b"; - t.type = "r"; - this.rightRotate(t); - n = t.left - } - if (n && (!n.left || n.left.type === "b") && (!n.right || n.right.type === "b")) { - n.type = "r"; - e = t - } else { - if (!n.left || n.left.type === "b") { - n.right.type = "b"; - n.type = "r"; - this.leftRotate(n); - n = t.left - } - n.type = t.type; - t.type = "b"; - n.left.type = "b"; - this.rightRotate(t); - e = this.root - } - } - t = e.parent - } - if (e)e.type = "b" -}; -RBTree.prototype.successor = function (e) { - if (e.right)return this.minimum(e.right); - var t = e.parent; - while (t && e === t.right) { - e = t; - t = t.parent - } - return t -}; -RBTree.prototype.predecessor = function (e) { - if (e.left)return this.maximum(e.left); - var t = e.parent; - while (t && e === t.left) { - e = t; - t = t.parent - } - return t -}; -RBTree.prototype.search = function (e, t, n) { - t = t || this.root; - n = n || function (t) { - return t.key === e - }; - while (t && !n(t))if (e < t.key)t = t.left; else t = t.right; - if (t)return t.item; - return undefined -}; -RBTree.prototype.contains = function (e, t) { - return this.search(e, null, t) !== undefined -}; -RBTree.prototype.fullContains = function (e) { - var t = this.minimum(); - while (t && !e(t.key))t = this.successor(t); - return t !== null -}; -RBTree.prototype.minimum = function (e) { - e = e || this.root; - while (e && e.left)e = e.left; - return e -}; -RBTree.prototype.maximum = function (e) { - e = e || this.root; - while (e && e.right)e = e.right; - return e -}; -RBTree.prototype.leftRotate = function (e) { - var t = e.right; - e.right = t.left; - if (t.left !== null)t.left.parent = e; - t.parent = e.parent; - if (e.parent === null)this.root = t; else if (e === e.parent.left)e.parent.left = t; else e.parent.right = t; - e.parent = t; - t.left = e -}; -RBTree.prototype.rightRotate = function (e) { - var t = e.left; - e.left = t.right; - if (t.right !== null)t.right.parent = e; - t.parent = e.parent; - if (e.parent === null)this.root = t; else if (e === e.parent.left)e.parent.left = t; else e.parent.right = t; - e.parent = t; - t.right = e -}; -RBTree.prototype.getSize = function () { - return this.size -}; -RBTree.prototype.clone = function () { - var e = new RBTree; - var t = this.getIterator(); - for (t.first(); !t.isDone(); t.next())if (t.getNode().item.clone)e.insert(t.getNode().key, t.getNode().item.clone()); else e.insert(t.getNode().key, t.getNode().item); - return e -}; -RBTree.prototype.cloneDistinct = function () { - var e = new RBTree; - var t = this.getIterator(); - for (t.first(); !t.isDone(); t.next()) { - var n = function (e) { - return e.key === t.getNode().key && e.item === t.getNode().item - }; - if (!e.contains(t.getNode().key, n)) { - if (t.getNode().item.cloneDistinct)e.insert(t.getNode().key, t.getNode().item.cloneDistinct()); else if (t.getNode().item.clone)e.insert(t.getNode().key, t.getNode().item.clone()); else e.insert(t.getNode().key, t.getNode().item) - } - } - return e -}; -RBTree.prototype.toArray = function () { - var e = []; - for (var t = this.minimum(); t; t = this.successor(t))e.push(t.item); - return e -}; -RBTree.prototype.clear = function () { - this.root = null; - this.size = 0 -}; -RBTree.prototype.isEmpty = function () { - return!this.size -}; -RBTree.prototype.execute = function (e) { - for (var t = this.minimum(); t; t = this.successor(t))t.item = e(t.item) -}; -RBTree.prototype.filter = function (e) { - var t = []; - for (var n = this.minimum(); n; n = this.successor(n))if (e(n.item))t.push(n.item); - return t -}; -RBTree.prototype.indexOf = function (e, t) { - t = t || function (t) { - return t === e - }; - var n = 0, r = this.minimum(); - while (r) { - if (t(r.item))return n; - r = this.successor(r); - n++ - } - return-1 -}; -RBTree.prototype.lastIndexOf = function (e, t) { - t = t || function (t) { - return t === e - }; - var n = this.size - 1, r = this.maximum(); - while (r) { - if (t(r.item))return n; - n--; - r = this.predecessor(r) - } - return-1 -}; -RBTree.prototype.allIndexesOf = function (e, t) { - t = t || function (t) { - return t === e - }; - var n = 0, r = this.minimum(); - var i = []; - while (r) { - if (t(r.item))i.push(n); - n++; - r = this.successor(r) - } - return i -}; -RBTree.prototype.getItem = function (e) { - if (e < 0 || e > this.size - 1)return undefined; - for (var t = this.minimum(), n = 0; n < e; t = this.successor(t))n++; - return t.item -}; -RBTreeIterator.prototype = new Iterator; -RBTreeIterator.prototype.constructor = RBTreeIterator; -RBTreeIterator.prototype.first = function () { - this.pointer = this.aggregate.minimum() -}; -RBTreeIterator.prototype.next = function () { - this.pointer = this.aggregate.successor(this.pointer) -}; -RBTreeIterator.prototype.last = function () { - this.pointer = this.aggregate.maximum() -}; -RBTreeIterator.prototype.previous = function () { - this.pointer = this.aggregate.predecessor(this.pointer) -}; -RBTreeIterator.prototype.isDone = function () { - return!this.pointer -}; -RBTreeIterator.prototype.getItem = function () { - return this.pointer.item -}; -RBTreeIterator.prototype.getNode = function () { - return this.pointer -}; -RBTreeList.prototype = new Aggregate; -RBTreeList.prototype.constructor = RBTreeList; -RBTreeList.prototype.getIterator = function () { - return new RBTreeListIterator(this) -}; -RBTreeList.prototype.insert = function (e, t) { - var n = new RBLNode(e, t); - this.size++; - if (!this.root) { - this.root = n; - this.first = n; - this.last = n; - n.type = "b"; - return - } - var r = this.root; - for (var i = this.root; i;) { - r = i; - if (e < i.key)i = i.left; else i = i.right - } - n.parent = r; - if (!r)this.root = n; else if (e < r.key)r.left = n; else r.right = n; - n.next = this.successor(n); - if (n.next) { - if (n.next.previous)n.next.previous.next = n; else this.first = n; - n.previous = n.next.previous; - n.next.previous = n - } else { - this.last = n; - n.previous = this.predecessor(n); - if (n.previous)n.previous.next = n; else this.first = n - } - this.insertFixUp(n) -}; -RBTreeList.prototype.insertFixUp = function (e) { - for (var t = e.parent; t && t.type === "r"; t = e.parent) { - if (t === t.parent.left) { - var n = t.parent.right; - if (n && n.type === "r") { - t.type = "b"; - n.type = "b"; - t.parent.type = "r"; - e = t.parent - } else if (e === t.right) { - e = t; - this.leftRotate(e) - } else { - t.type = "b"; - t.parent.type = "r"; - this.rightRotate(t.parent) - } - } else { - var n = t.parent.left; - if (n && n.type === "r") { - t.type = "b"; - n.type = "b"; - t.parent.type = "r"; - e = t.parent - } else if (e === t.left) { - e = t; - this.rightRotate(e) - } else { - t.type = "b"; - t.parent.type = "r"; - this.leftRotate(t.parent) - } - } - } - this.root.type = "b" -}; -RBTreeList.prototype.deleteNode = function (e) { - this.size--; - var t; - if (!e.left || !e.right)t = e; else { - t = this.successor(e); - e.key = t.key; - e.item = t.item - } - var n; - if (!t.left)n = t.right; else n = t.left; - if (n)n.parent = t.parent; - if (!t.parent)this.root = n; else if (t === t.parent.left)t.parent.left = n; else t.parent.right = n; - if (t.next)t.next.previous = t.previous; else this.last = t.previous; - if (t.previous)t.previous.next = t.next; else this.first = t.next; - if (t.type === "b")this.deleteFixUp(n, t.parent) -}; -RBTreeList.prototype.deleteFixUp = function (e, t) { - while (e !== this.root && (!e || e.type === "b")) { - if (e === t.left) { - var n = t.right; - if (n && n.type === "r") { - n.type = "b"; - t.type = "r"; - this.leftRotate(t); - n = t.right - } - if (n && (!n.left || n.left.type === "b") && (!n.right || n.right.type === "b")) { - n.type = "r"; - e = t - } else { - if (!n.right || n.right.type === "b") { - n.left.type = "b"; - n.type = "r"; - this.rightRotate(n); - n = t.right - } - n.type = t.type; - t.type = "b"; - n.right.type = "b"; - this.leftRotate(t); - e = this.root - } - } else { - var n = t.left; - if (n && n.type === "r") { - n.type = "b"; - t.type = "r"; - this.rightRotate(t); - n = t.left - } - if (n && (!n.left || n.left.type === "b") && (!n.right || n.right.type === "b")) { - n.type = "r"; - e = t - } else { - if (!n.left || n.left.type === "b") { - n.right.type = "b"; - n.type = "r"; - this.leftRotate(n); - n = t.left - } - n.type = t.type; - t.type = "b"; - n.left.type = "b"; - this.rightRotate(t); - e = this.root - } - } - t = e.parent - } - if (e)e.type = "b" -}; -RBTreeList.prototype.successor = function (e) { - if (e.next || e === this.last)return e.next; - if (e.right)return this.minimum(e.right); - var t = e.parent; - while (t && e === t.right) { - e = t; - t = t.parent - } - return t -}; -RBTreeList.prototype.predecessor = function (e) { - if (e.previous || e === this.first)return e.previous; - if (e.left)return this.maximum(e.left); - var t = e.parent; - while (t && e === t.left) { - e = t; - t = t.parent - } - return t -}; -RBTreeList.prototype.search = function (e, t, n) { - t = t || this.root; - n = n || function (t) { - return t.key === e - }; - while (t && !n(t))if (e < t.key)t = t.left; else t = t.right; - if (t)return t.item; - return undefined -}; -RBTreeList.prototype.contains = function (e, t) { - return this.search(e, null, t) !== undefined -}; -RBTreeList.prototype.fullContains = function (e) { - var t = this.first; - while (t && !e(t.key))t = t.next; - return t !== null -}; -RBTreeList.prototype.minimum = function (e) { - if (e)while (e && e.left)e = e.left; else return this.first; - return e -}; -RBTreeList.prototype.maximum = function (e) { - if (e)while (e && e.right)e = e.right; else return this.last; - return e -}; -RBTreeList.prototype.leftRotate = function (e) { - var t = e.right; - e.right = t.left; - if (t.left !== null)t.left.parent = e; - t.parent = e.parent; - if (e.parent === null)this.root = t; else if (e === e.parent.left)e.parent.left = t; else e.parent.right = t; - e.parent = t; - t.left = e -}; -RBTreeList.prototype.rightRotate = function (e) { - var t = e.left; - e.left = t.right; - if (t.right !== null)t.right.parent = e; - t.parent = e.parent; - if (e.parent === null)this.root = t; else if (e === e.parent.left)e.parent.left = t; else e.parent.right = t; - e.parent = t; - t.right = e -}; -RBTreeList.prototype.getSize = function () { - return this.size -}; -RBTreeList.prototype.clone = function () { - var e = new RBTreeList; - var t = this.getIterator(); - for (t.first(); !t.isDone(); t.next())e.insert(t.getNode().key, t.getNode().item); - return e -}; -RBTreeList.prototype.cloneDistinct = function () { - var e = new RBTreeList; - var t = this.getIterator(); - for (t.first(); !t.isDone(); t.next()) { - var n = function (e) { - return e.key === t.getNode().key && e.item === t.getNode().item - }; - if (!e.contains(t.getNode().key, n)) { - if (t.getNode().item.cloneDistinct)e.insert(t.getNode().key, t.getNode().item.cloneDistinct()); else if (t.getNode().item.clone)e.insert(t.getNode().key, t.getNode().item.clone()); else e.insert(t.getNode().key, t.getNode().item) - } - } - return e -}; -RBTreeList.prototype.toArray = function () { - var e = []; - for (var t = this.first; t; t = t.next)e.push(t.item); - return e -}; -RBTreeList.prototype.clear = function () { - this.root = null; - this.first = null; - this.last = null; - this.size = 0 -}; -RBTreeList.prototype.isEmpty = function () { - return!this.size -}; -RBTreeList.prototype.execute = function (e) { - for (var t = this.first; t; t = t.next)t.item = e(t.item) -}; -RBTreeList.prototype.filter = function (e) { - var t = []; - for (var n = this.first; n; n = n.next)if (e(n.item))t.push(n.item); - return t -}; -RBTreeList.prototype.indexOf = function (e, t) { - t = t || function (t) { - return t === e - }; - var n = 0, r = this.first; - while (r) { - if (t(r.item))return n; - r = r.next; - n++ - } - return-1 -}; -RBTreeList.prototype.lastIndexOf = function (e, t) { - t = t || function (t) { - return t === e - }; - var n = this.size - 1, r = this.last; - while (r) { - if (t(r.item))return n; - n--; - r = r.previous - } - return-1 -}; -RBTreeList.prototype.allIndexesOf = function (e, t) { - t = t || function (t) { - return t === e - }; - var n = 0, r = this.first; - var i = []; - while (r) { - if (t(r.item))i.push(n); - n++; - r = r.next - } - return i -}; -RBTreeList.prototype.getItem = function (e) { - if (e < 0 || e > this.size - 1)return undefined; - for (var t = this.first, n = 0; n < e; t = t.next)n++; - return t.item -}; -RBTreeListIterator.prototype = new Iterator; -RBTreeListIterator.prototype.constructor = RBTreeListIterator; -RBTreeListIterator.prototype.first = function () { - this.pointer = this.aggregate.first -}; -RBTreeListIterator.prototype.next = function () { - this.pointer = this.pointer.next -}; -RBTreeListIterator.prototype.last = function () { - this.pointer = this.aggregate.last -}; -RBTreeListIterator.prototype.previous = function () { - this.pointer = this.pointer.previous -}; -RBTreeListIterator.prototype.isDone = function () { - return!this.pointer -}; -RBTreeListIterator.prototype.getItem = function () { - return this.pointer.item -}; -RBTreeListIterator.prototype.getNode = function () { - return this.pointer -}; -Set.prototype.insert = function (e) { - this.elements.pushBack(e); - e.parents.pushBack(this); - this.size++ -}; -Set.prototype.multiInsert = function (e) { - for (var t = 0; t < e.length; t++) { - this.elements.pushBack(e[t]); - e[t].parents.pushBack(this) - } - this.size += e.length -}; -Set.prototype.union = function (e) { - var t = new Set; - t.addSubsets([this, e]); - this.parents.pushBack(t); - e.parents.pushBack(t); - var n = this; - var r = function (e) { - if (e === n)return t - }; - var i = this.sets.getIterator(); - for (i.first(); !i.isDone(); i.next())i.getItem().parents.execute(r); - r = function (n) { - if (n === e)return t - }; - i = e.sets.getIterator(); - for (i.first(); !i.isDone(); i.next())i.getItem().parents.execute(r); - return t -}; -Set.prototype.intersect = function (e) { - var t = new Set; - var n = this.elements.getIterator(); - for (n.first(); !n.isDone(); n.next())if (n.getItem().parents.contains(e))t.insert(n.getItem()); - var r = this.sets.getIterator(); - for (r.first(); !r.isDone(); r.next()) { - n = r.getItem().getIterator(); - for (n.first(); !n.isDone(); n.next())if (n.getItem().parents.contains(e))t.insert(n.getItem()) - } - return t -}; -Set.prototype.difference = function (e) { - var t = new Set; - var n = this.elements.getIterator(); - for (n.first(); !n.isDone(); n.next())if (!n.getItem().parents.contains(e))t.insert(n.getItem()); - var r = this.sets.getIterator(); - for (r.first(); !r.isDone(); r.next()) { - n = r.getItem().getIterator(); - for (n.first(); !n.isDone(); n.next())if (!n.getItem().parents.contains(e))t.insert(n.getItem()) - } - return t -}; -Set.prototype.cartesianProduct = function (e) { - var t = this.getItems(); - var n = e.getItems(); - var r = new Set; - for (var i = 0; i < t.length; i++)for (var s = 0; s < n.length; s++)r.insert(new Element([t[i], n[s]])); - return r -}; -Set.prototype.addSubset = function (e) { - this.sets.pushBack(e); - this.size += e.size -}; -Set.prototype.addSubsets = function (e) { - for (var t = 0; t < e.length; t++)this.addSubset(e[t]) -}; -Set.prototype.getItems = function () { - var e = []; - var t = this.elements.getIterator(); - for (t.first(); !t.isDone(); t.next())e.push(t.getItem().item); - var n = this.sets.getIterator(); - for (n.first(); !n.isDone(); n.next()) { - t = n.getItem().getIterator(); - for (t.first(); !t.isDone(); t.next())e.push(t.getItem().item) - } - return e -}; -Set.prototype.getCardinality = function () { - return this.size -}; -Set.prototype.isEmpty = function () { - return!this.size -}; -Set.prototype.clone = function () { - var e = new Set; - e.parents = this.parents.clone(); - e.elements = this.elements.clone(); - e.sets = this.sets.clone(); - e.size = this.size; - return e -}; -Stack.prototype = new Aggregate; -Stack.prototype.constructor = Stack; -Stack.prototype.getIterator = function () { - return new StackIterator(this) -}; -Stack.prototype.push = function (e) { - this.items.push(e) -}; -Stack.prototype.multiPush = function (e) { - for (var t = 0; t < e.length; t++)this.push(e[t]) -}; -Stack.prototype.pop = function () { - if (!this.items.length)return undefined; - return this.items.pop() -}; -Stack.prototype.multiPop = function (e) { - var t = []; - for (var n = 0; n < e && this.items.length; n++)t.push(this.pop()); - return t -}; -Stack.prototype.peek = function () { - if (!this.items.length)return undefined; - return this.items[this.items.length - 1] -}; -Stack.prototype.clear = function () { - this.items = [] -}; -Stack.prototype.contains = function (e, t) { - t = t || function (t) { - return t === e - }; - var n = 0; - while (n < this.items.length && !t(this.items[n]))n++; - return n < this.items.length -}; -Stack.prototype.execute = function (e) { - for (var t = this.items.length - 1; t > -1; t--)this.items[t] = e(this.items[t]) -}; -Stack.prototype.getItem = function (e) { - if (e < 0 || e > this.items.length - 1)return undefined; - return this.items[this.items.length - e - 1] -}; -Stack.prototype.getLength = function () { - return this.items.length -}; -Stack.prototype.isEmpty = function () { - return!this.items.length -}; -Stack.prototype.filter = function (e) { - var t = []; - for (var n = this.items.length - 1; n > -1; n--) { - if (e(this.items[n]))t.push(this.items[n]) - } - return t -}; -Stack.prototype.indexOf = function (e, t) { - t = t || function (t) { - return t === e - }; - var n = this.items.length - 1; - while (n > -1) { - if (t(this.items[n]))return n; - n-- - } - return-1 -}; -Stack.prototype.lastIndexOf = function (e, t) { - t = t || function (t) { - return t === e - }; - var n = 0; - while (n < this.items.length) { - if (t(this.items[n]))return n; - n++ - } - return-1 -}; -Stack.prototype.allIndexesOf = function (e, t) { - t = t || function (t) { - return t === e - }; - var n = this.items.length - 1; - var r = []; - while (n > -1) { - if (t(this.items[n]))r.push(n); - n-- - } - return r -}; -Stack.prototype.clone = function () { - var e = new Stack; - for (var t = 0; t < this.items.length; t++)if (this.items[t].clone)e.push(this.items[t].clone()); else e.push(this.items[t]); - return e -}; -Stack.prototype.cloneDistinct = function () { - var e = new Stack; - for (var t = 0; t < this.items.length; t++)if (!e.contains(this.items[t])) { - if (this.items[t].cloneDistinct)e.push(this.items[t].cloneDistinct()); else if (this.items[t].clone)e.push(this.items[t].clone()); else e.push(this.items[t]) - } - return e -}; -StackIterator.prototype = new Iterator; -StackIterator.prototype.constructor = StackIterator; -StackIterator.prototype.first = function () { - this.pointer = this.aggregate.items.length - 1 -}; -StackIterator.prototype.next = function () { - this.pointer-- -}; -StackIterator.prototype.last = function () { - this.pointer = 0 -}; -StackIterator.prototype.previous = function () { - this.pointer++ -}; -StackIterator.prototype.isDone = function () { - return this.pointer < 0 || this.pointer > this.aggregate.items.length - 1 -}; -StackIterator.prototype.getItem = function () { - return this.aggregate.items[this.pointer] -} diff --git a/Tests/BSTree_Test.js b/Tests/BSTree_Test.js deleted file mode 100644 index 9be2a60..0000000 --- a/Tests/BSTree_Test.js +++ /dev/null @@ -1,82 +0,0 @@ -/** - * Created by Stefano on 06/04/14. - */ - -test("BSTree - Insert test", function () { - var tree = new BSTree(); - var keys = []; - for (var i = 0; i < 20; i++) { - keys.push(Math.random()); - tree.insert(keys[i], i); - } - for (var j = 0; j < 20; j++) - deepEqual(tree.search(keys[j]), j, "Insert node"); -}); - -test("BSTree - Minimum test", function () { - var tree = new BSTree(); - var keys = []; - var min = 10; - for (var i = 0; i < 20; i++) { - keys.push(Math.random()); - tree.insert(keys[i], i); - if (keys[i] < min) - min = keys[i]; - } - deepEqual(tree.minimum().item, tree.search(min), "Minimum"); -}); - -test("BSTree - Maximum test", function () { - var tree = new BSTree(); - var keys = []; - var max = -1; - for (var i = 0; i < 20; i++) { - keys.push(Math.random()); - tree.insert(keys[i], i); - if (keys[i] > max) - max = keys[i]; - } - deepEqual(tree.maximum().item, tree.search(max), "Maximum"); -}); - -test("BSTree - Successor test", function () { - var tree = new BSTree(); - for (var i = 0; i < 20; i++) - tree.insert(i, i); - var it = tree.getIterator(); - var j = 1; - for (it.first(); !it.isDone(); it.next(), j++) { - var successor = tree.successor(it.getNode()); - if (successor) - deepEqual(successor.item, j, "Successor"); - else - deepEqual(successor, null, "No successor"); - } -}); - -test("BSTree - Predecessor test", function () { - var tree = new BSTree(); - for (var i = 0; i < 20; i++) - tree.insert(i, i); - var it = tree.getIterator(); - var j = 18; - for (it.last(); !it.isDone(); it.previous(), j--) { - var predecessor = tree.predecessor(it.getNode()); - if (predecessor) - deepEqual(predecessor.item, j, "Predecessor"); - else - deepEqual(predecessor, null, "No predecessor"); - } -}); - -test("BSTree - Delete node test", function () { - var tree = new BSTree(); - for (var i = 0; i < 20; i++) - tree.insert(i, i); - var j = 0; - while (tree.minimum()) { - deepEqual(tree.minimum().item, j, "Deletion"); - tree.deleteNode(tree.minimum()); - j++; - } -}); \ No newline at end of file diff --git a/Tests/BSTree_Test.ts b/Tests/BSTree_Test.ts new file mode 100644 index 0000000..1f08e16 --- /dev/null +++ b/Tests/BSTree_Test.ts @@ -0,0 +1,94 @@ +/** + * Created by Stefano on 06/04/14. + */ + +QUnit.test("BSTree - Insert test", function (assert) +{ + var tree = new ds.BSTree(); + var keys = []; + for (var i = 0; i < 20; i++) + { + keys.push(Math.random()); + tree.insert(keys[i], i); + } + for (var j = 0; j < 20; j++) + assert.deepEqual(tree.search(keys[j]), j, "Insert node"); +}); + +QUnit.test("BSTree - Minimum test", function (assert) +{ + var tree = new ds.BSTree(); + var keys = []; + var min = 10; + for (var i = 0; i < 20; i++) + { + keys.push(Math.random()); + tree.insert(keys[i], i); + if (keys[i] < min) + min = keys[i]; + } + assert.deepEqual(tree.minimum().item, tree.search(min), "Minimum"); +}); + +QUnit.test("BSTree - Maximum test", function (assert) +{ + var tree = new ds.BSTree(); + var keys = []; + var max = -1; + for (var i = 0; i < 20; i++) + { + keys.push(Math.random()); + tree.insert(keys[i], i); + if (keys[i] > max) + max = keys[i]; + } + assert.deepEqual(tree.maximum().item, tree.search(max), "Maximum"); +}); + +QUnit.test("BSTree - Successor test", function (assert) +{ + var tree = new ds.BSTree(); + for (var i = 0; i < 20; i++) + tree.insert(i, i); + var it = tree.getIterator(); + var j = 1; + for (it.first(); !it.isDone(); it.next(), j++) + { + var successor = tree.successor(it.getNode()); + if (successor) + assert.deepEqual(successor.item, j, "Successor"); + else + assert.deepEqual(successor, null, "No successor"); + } +}); + +QUnit.test("BSTree - Predecessor test", function (assert) +{ + var tree = new ds.BSTree(); + for (var i = 0; i < 20; i++) + tree.insert(i, i); + var it = tree.getIterator(); + var j = 18; + for (it.last(); !it.isDone(); it.previous(), j--) + { + var predecessor = tree.predecessor(it.getNode()); + if (predecessor) + assert.deepEqual(predecessor.item, j, "Predecessor"); + else + assert.deepEqual(predecessor, null, "No predecessor"); + } +}); + +QUnit.test("BSTree - Delete node test", function (assert) +{ + var tree = new ds.BSTree(); + for (var i = 0; i < 20; i++) + tree.insert(i, i); + var j = 0; + while (tree.minimum()) + { + assert.deepEqual(tree.minimum().item, j, "Deletion"); + tree.deleteNode(tree.minimum()); + j++; + } +}); \ No newline at end of file diff --git a/Tests/BTree_Test.js b/Tests/BTree_Test.js deleted file mode 100644 index de73fc6..0000000 --- a/Tests/BTree_Test.js +++ /dev/null @@ -1,190 +0,0 @@ -/** - * Created by Stefano on 06/04/14. - */ - -test("BTree - Insert test", function () { - var tree = new BTree(100); - for (var i = 0; i < 100; i++) - tree.insert(i, i); - for (var j = 0; j < 100; j++) { - deepEqual(tree.search(j), j, "Insert node"); - deepEqual(tree.getItem(j), j, "Insert node"); - } -}); - -test("BTree - Delete node test", function () { - var tree = new BTree(3); - for (var i = 0; i < 20; i++) - tree.insert(i, i); - tree.deleteKey(6); - deepEqual(tree.search(6), undefined, "Delete node 6"); -}); - -test("BTree - Successor test", function () { - var tree = new BTree(3); - for (var i = 0; i < 20; i++) - tree.insert(i, i); - for (var j = -1; j < 19; j++) - deepEqual(tree.successor(j), j + 1, "Successor found"); - deepEqual(tree.successor(19), null, "Successor not found"); -}); - -test("BTree - Predecessor test", function () { - var tree = new BTree(4); - for (var i = 0; i < 40; i++) - tree.insert(i, i); - for (var j = 40; j > 0; j--) - deepEqual(tree.predecessor(j), j - 1, "Predecessor"); - deepEqual(tree.predecessor(0), null, "Predecessor not found"); -}); - -test("BTree - Minimum test", function () { - var tree = new BTree(3); - var keys = []; - var min = 10; - for (var i = 0; i < 20; i++) { - keys.push(Math.random()); - tree.insert(keys[i], i); - if (keys[i] < min) - min = keys[i]; - } - deepEqual(tree.minimum(), tree.search(min), "Minimum item"); - deepEqual(tree.minimumKey(), min, "Minimum key"); -}); - -test("BTree - Maximum test", function () { - var tree = new BTree(3); - var keys = []; - var max = -1; - for (var i = 0; i < 20; i++) { - keys.push(Math.random()); - tree.insert(keys[i], i); - if (keys[i] > max) - max = keys[i]; - } - deepEqual(tree.maximum(), tree.search(max), "Maximum item"); - deepEqual(tree.maximumKey(), max, "Maximum key"); -}); - -test("BTree - To array test", function () { - var tree = new BTree(3); - for (var i = 0; i < 5; i++) - tree.insert(i, i); - deepEqual(tree.toArray(), [0, 1, 2, 3, 4], "To array"); -}); - -test("BTree - Filter test", function () { - var tree = new BTree(3); - - for (var i = 0; i < 10; i++) - tree.insert(i, i); - - var result = tree.filter(function (item) { - return 1 - item % 2; - }); - deepEqual(result, [0, 2, 4, 6, 8], "Filter on the even values"); -}); - -test("BTree - Clear test", function () { - var tree = new BTree(3); - tree.insert(0, 0); - tree.insert(2, 2); - tree.clear(); - deepEqual(tree.isEmpty(), true, "Clear tree"); -}); - -test("BTree - Is empty test", function () { - var tree = new BTree(3); - tree.insert(0, 0); - tree.insert(2, 2); - deepEqual(tree.isEmpty(), false, "Is not empty"); - tree.clear(); - deepEqual(tree.isEmpty(), true, "Is empty"); -}); - -test("BTree - Contains test", function () { - var tree = new BTree(3); - tree.insert(0, 0); - tree.insert(2, 2); - deepEqual(tree.contains(0), true, "Contains 0"); - deepEqual(tree.contains(2), true, "Contains 2"); - deepEqual(tree.contains(1), false, "Not contains 1"); - var callback = function (item) { - return item > 0; - }; - deepEqual(tree.fullContains(callback), true, "Contains a value > 0"); - callback = function (item) { - return item < 0; - }; - deepEqual(tree.fullContains(callback), false, "Contains a value < 0"); -}); - -test("BTree - Execute test", function () { - var tree = new BTree(); - tree.insert(0, 0); - tree.insert(2, 2); - var callback = function (item) { - return item * 2; - }; - tree.execute(callback); - deepEqual(tree.search(0), 0, "Execute for key 0"); - deepEqual(tree.search(2), 4, "Execute for key 1"); -}); - -test("BTree - Index of test", function () { - var tree = new BTree(3); - for (var i = 0; i < 10; i++) - tree.insert(i, i); - var callback = function (item) { - return !(item % 2) && item > 5; - }; - deepEqual(tree.indexOf(0), 0, "Index of 0"); - deepEqual(tree.indexOf(15), -1, "Index of 15"); - deepEqual(tree.indexOf(5), 5, "Index of 5"); - deepEqual(tree.indexOf(null, callback), 6, "Index of the first even number greater than 5"); -}); - -test("BTree - Last index of test", function () { - var tree = new BTree(3); - for (var i = 0; i < 10; i++) - tree.insert(i, i); - var callback = function (item) { - return !(item % 2) && item > 5; - }; - deepEqual(tree.lastIndexOf(0), 0, "Last index of 0"); - deepEqual(tree.lastIndexOf(15), -1, "Last index of 15"); - deepEqual(tree.lastIndexOf(5), 5, "Last index of 5"); - deepEqual(tree.lastIndexOf(null, callback), 8, "Index of the last even number greater than 5"); -}); - -test("BTree - Indexes of test", function () { - var tree = new BTree(3); - for (var i = 0; i < 30; i++) - tree.insert(i, i % 10); - var callback = function (item) { - return !(item % 2) && item > 5; - }; - deepEqual(tree.allIndexesOf(0), [0, 10, 20], "Indexes of 0"); - deepEqual(tree.allIndexesOf(15), [], "Indexes of 15"); - deepEqual(tree.allIndexesOf(5), [5, 15, 25], "Indexes of 5"); - deepEqual(tree.allIndexesOf(null, callback), [6, 8, 16, 18, 26, 28], "Indexes of the even numbers greater than 5"); -}); - -test("BTree - Clone test", function () { - var tree = new BTree(3); - for (var i = 0; i < 10; i++) - tree.insert(i, i); - var clone = tree.clone(); - var it = clone.getIterator(); - var j = 0; - for (it.first(); !it.isDone(); it.next(), j++) - deepEqual(it.getItem(), j, "Clone of the tree"); -}); - -test("BTree - Clone distinct test", function () { - var tree = new BTree(3); - for (var i = 0; i < 20; i++) - tree.insert(i, i % 10); - var clone = tree.cloneDistinct(); - deepEqual(clone.allIndexesOf(2), [2], "Clone of the tree"); -}); \ No newline at end of file diff --git a/Tests/BTree_Test.ts b/Tests/BTree_Test.ts new file mode 100644 index 0000000..787f6c7 --- /dev/null +++ b/Tests/BTree_Test.ts @@ -0,0 +1,217 @@ +/** + * Created by Stefano on 06/04/14. + */ + +QUnit.test("BTree - Insert test", function (assert) +{ + var tree = new ds.BTree(100); + for (var i = 0; i < 100; i++) + tree.insert(i, i); + for (var j = 0; j < 100; j++) + { + assert.deepEqual(tree.search(j), j, "Insert node"); + assert.deepEqual(tree.getItem(j), j, "Insert node"); + } +}); + +QUnit.test("BTree - Delete node test", function (assert) +{ + var tree = new ds.BTree(3); + for (var i = 0; i < 20; i++) + tree.insert(i, i); + tree.deleteKey(6); + assert.deepEqual(tree.search(6), undefined, "Delete node 6"); +}); + +QUnit.test("BTree - Successor test", function (assert) +{ + var tree = new ds.BTree(3); + for (var i = 0; i < 20; i++) + tree.insert(i, i); + for (var j = -1; j < 19; j++) + assert.deepEqual(tree.successor(j), j + 1, "Successor found"); + assert.deepEqual(tree.successor(19), -1, "Successor not found"); +}); + +QUnit.test("BTree - Predecessor test", function (assert) +{ + var tree = new ds.BTree(4); + for (var i = 0; i < 40; i++) + tree.insert(i, i); + for (var j = 40; j > 0; j--) + assert.deepEqual(tree.predecessor(j), j - 1, "Predecessor"); + assert.deepEqual(tree.predecessor(0), -1, "Predecessor not found"); +}); + +QUnit.test("BTree - Minimum test", function (assert) +{ + var tree = new ds.BTree(3); + var keys = []; + var min = 10; + for (var i = 0; i < 20; i++) + { + keys.push(Math.random()); + tree.insert(keys[i], i); + if (keys[i] < min) + min = keys[i]; + } + assert.deepEqual(tree.minimum(), tree.search(min), "Minimum item"); + assert.deepEqual(tree.minimumKey(), min, "Minimum key"); +}); + +QUnit.test("BTree - Maximum test", function (assert) +{ + var tree = new ds.BTree(3); + var keys = []; + var max = -1; + for (var i = 0; i < 20; i++) + { + keys.push(Math.random()); + tree.insert(keys[i], i); + if (keys[i] > max) + max = keys[i]; + } + assert.deepEqual(tree.maximum(), tree.search(max), "Maximum item"); + assert.deepEqual(tree.maximumKey(), max, "Maximum key"); +}); + +QUnit.test("BTree - To array test", function (assert) +{ + var tree = new ds.BTree(3); + for (var i = 0; i < 5; i++) + tree.insert(i, i); + assert.deepEqual(tree.toArray(), [0, 1, 2, 3, 4], "To array"); +}); + +QUnit.test("BTree - Filter test", function (assert) +{ + var tree = new ds.BTree(3); + + for (var i = 0; i < 10; i++) + tree.insert(i, i); + + var result = tree.filter(function (item) + { + return Boolean(1 - item % 2); + }); + assert.deepEqual(result, [0, 2, 4, 6, 8], "Filter on the even values"); +}); + +QUnit.test("BTree - Clear test", function (assert) +{ + var tree = new ds.BTree(3); + tree.insert(0, 0); + tree.insert(2, 2); + tree.clear(); + assert.deepEqual(tree.isEmpty(), true, "Clear tree"); +}); + +QUnit.test("BTree - Is empty test", function (assert) +{ + var tree = new ds.BTree(3); + tree.insert(0, 0); + tree.insert(2, 2); + assert.deepEqual(tree.isEmpty(), false, "Is not empty"); + tree.clear(); + assert.deepEqual(tree.isEmpty(), true, "Is empty"); +}); + +QUnit.test("BTree - Contains test", function (assert) +{ + var tree = new ds.BTree(3); + tree.insert(0, 0); + tree.insert(2, 2); + assert.deepEqual(tree.contains(0), true, "Contains 0"); + assert.deepEqual(tree.contains(2), true, "Contains 2"); + assert.deepEqual(tree.contains(1), false, "Not contains 1"); + var callback = function (item) + { + return item > 0; + }; + assert.deepEqual(tree.fullContains(callback), true, "Contains a value > 0"); + callback = function (item) + { + return item < 0; + }; + assert.deepEqual(tree.fullContains(callback), false, "Contains a value < 0"); +}); + +QUnit.test("BTree - Execute test", function (assert) +{ + var tree = new ds.BTree(); + tree.insert(0, 0); + tree.insert(2, 2); + var callback = function (item) + { + return item * 2; + }; + tree.execute(callback); + assert.deepEqual(tree.search(0), 0, "Execute for key 0"); + assert.deepEqual(tree.search(2), 4, "Execute for key 1"); +}); + +QUnit.test("BTree - Index of test", function (assert) +{ + var tree = new ds.BTree(3); + for (var i = 0; i < 10; i++) + tree.insert(i, i); + var callback = function (item) + { + return !(item % 2) && item > 5; + }; + assert.deepEqual(tree.indexOf(0), 0, "Index of 0"); + assert.deepEqual(tree.indexOf(15), -1, "Index of 15"); + assert.deepEqual(tree.indexOf(5), 5, "Index of 5"); + assert.deepEqual(tree.indexOf(null, callback), 6, "Index of the first even number greater than 5"); +}); + +QUnit.test("BTree - Last index of test", function (assert) +{ + var tree = new ds.BTree(3); + for (var i = 0; i < 10; i++) + tree.insert(i, i); + var callback = function (item) + { + return !(item % 2) && item > 5; + }; + assert.deepEqual(tree.lastIndexOf(0), 0, "Last index of 0"); + assert.deepEqual(tree.lastIndexOf(15), -1, "Last index of 15"); + assert.deepEqual(tree.lastIndexOf(5), 5, "Last index of 5"); + assert.deepEqual(tree.lastIndexOf(null, callback), 8, "Index of the last even number greater than 5"); +}); + +QUnit.test("BTree - Indexes of test", function (assert) +{ + var tree = new ds.BTree(3); + for (var i = 0; i < 30; i++) + tree.insert(i, i % 10); + var callback = function (item) + { + return !(item % 2) && item > 5; + }; + assert.deepEqual(tree.allIndexesOf(0), [0, 10, 20], "Indexes of 0"); + assert.deepEqual(tree.allIndexesOf(15), [], "Indexes of 15"); + assert.deepEqual(tree.allIndexesOf(5), [5, 15, 25], "Indexes of 5"); + assert.deepEqual(tree.allIndexesOf(null, callback), [6, 8, 16, 18, 26, 28], "Indexes of the even numbers greater than 5"); +}); + +QUnit.test("BTree - Clone test", function (assert) +{ + var tree = new ds.BTree(3); + for (var i = 0; i < 10; i++) + tree.insert(i, i); + var clone = tree.clone(); + var it = clone.getIterator(); + var j = 0; + for (it.first(); !it.isDone(); it.next(), j++) + assert.deepEqual(it.getItem(), j, "Clone of the tree"); +}); + +QUnit.test("BTree - Clone distinct test", function (assert) +{ + var tree = new ds.BTree(3); + for (var i = 0; i < 20; i++) + tree.insert(i, i % 10); + var clone = tree.cloneDistinct(); + assert.deepEqual(clone.allIndexesOf(2), [2], "Clone of the tree"); +}); \ No newline at end of file diff --git a/Tests/CircularBuffer_Test.js b/Tests/CircularBuffer_Test.js deleted file mode 100644 index 8a1a752..0000000 --- a/Tests/CircularBuffer_Test.js +++ /dev/null @@ -1,122 +0,0 @@ -/** - * Created by Battistella Stefano on 31/03/14. - */ - -test("CircularBuffer - Write test", function () { - var buffer = new CircularBuffer(10); - buffer.write(0); - buffer.write(0); - buffer.write(0); - buffer.write(0); - for (var i = 0; i < 4; i++) - deepEqual(buffer.read(i), 0, "Write 0"); - for (var j = 4; j < 10; j++) - deepEqual(buffer.read(j), undefined, "Write 0"); - buffer.write(1); - buffer.write(1); - buffer.write(1); - buffer.write(1); - buffer.write(1); - buffer.write(1); - buffer.write(1); - buffer.write(1); - for (var m = 4; m < 12; m++) - deepEqual(buffer.read(m), 1, "Write 1"); - for (var n = 2; n < 4; n++) - deepEqual(buffer.read(n), 0, "Write 1"); - deepEqual(buffer.isFull(), true, "Is full"); -}); - -test("CircularBuffer - Free test", function () { - var buffer = new CircularBuffer(10); - for (var k = 0; k < 12; k++) - buffer.write(k); - buffer.free(2, 8); - for (var i = 2; i < 8; i++) - deepEqual(buffer.read(i), undefined, "Free 2...8"); - deepEqual(buffer.head, 2, "Free 2...8"); - deepEqual(buffer.tail, 8, "Free 2...8"); - - for (var l = 0; l < 12; l++) - buffer.write(l); - deepEqual(buffer.head, 4, "Write 12 items"); - deepEqual(buffer.tail, 4, "Write 12 items"); - - buffer.free(8, 6); - for (var m = 8; m < 6; m = (m + 1) % 10) - deepEqual(buffer.read(m), undefined, "Free 8...6"); - deepEqual(buffer.head, 8, "Free 8...6"); - deepEqual(buffer.tail, 6, "Free 8...6"); - - buffer.freeAll(); - for (var j = 0; j < 10; j++) - deepEqual(buffer.read(j), undefined, "Free all"); - deepEqual(buffer.isEmpty(), true, "Is empty"); -}); - -test("CircularBuffer - Empty test", function () { - var buffer = new CircularBuffer(10); - buffer.write(0); - buffer.write(0); - buffer.write(0); - deepEqual(buffer.isEmpty(), false, "Is not empty"); - buffer.free(0, 8); - deepEqual(buffer.isEmpty(), true, "Is empty"); -}); - -test("CircularBuffer - Clone test", function () { - var buffer = new CircularBuffer(10); - for (var i = 0; i < 15; i++) - buffer.write(i); - var clone = buffer.clone(); - for (var j = 0; j < 9; j++) - deepEqual(clone.read(j), buffer.read(j), "Check items"); - deepEqual(clone.head, buffer.head, "Check head position"); - deepEqual(clone.tail, buffer.tail, "Check tail position"); - deepEqual(clone.isEmpty(), buffer.isEmpty(), "Check empty"); - deepEqual(clone.isFull(), buffer.isFull(), "Check empty"); -}); - -test("CircularBuffer - Resize test", function () { - var buffer = new CircularBuffer(5); - for (var i = 0; i < 8; i++) - buffer.write(i); - var clone = buffer.clone(); - buffer.resize(10); - deepEqual(buffer.head, 8, "Check head position"); - deepEqual(buffer.tail, 3, "Check tail position"); - for (var j = 0; j < 10; j++) - if (j < 3 || j > 7) - deepEqual(buffer.read(j), undefined, "Increase size"); - else - deepEqual(buffer.read(j), j, "Augment resize"); - buffer = clone; - buffer.resize(3); - deepEqual(buffer.head, 0, "Check head position"); - deepEqual(buffer.tail, 0, "Check tail position"); - for (var k = 0; k < 3; k++) - deepEqual(buffer.read(k), k + 3, "Decrease size"); -}); - -test("CircularBuffer - Iterator test", function () { - var buffer = new CircularBuffer(10); - var it = buffer.getIterator(); - it.first(); - deepEqual(it.isDone(), true, "Check empty buffer iterator"); - buffer.write(0); - buffer.write(0); - buffer.write(0); - buffer.write(0); - buffer.write(1); - buffer.write(1); - buffer.write(1); - buffer.write(1); - buffer.write(1); - buffer.write(1); - buffer.write(1); - buffer.write(1); - var result = [0, 0, 1, 1, 1, 1, 1, 1, 1, 1]; - var i = 0; - for (it.first(); !it.isDone(); it.next(), i++) - deepEqual(it.getItem(), result[i], "Check iterator"); -}); \ No newline at end of file diff --git a/Tests/CircularBuffer_Test.ts b/Tests/CircularBuffer_Test.ts new file mode 100644 index 0000000..bc12993 --- /dev/null +++ b/Tests/CircularBuffer_Test.ts @@ -0,0 +1,128 @@ +/** + * Created by Battistella Stefano on 31/03/14. + */ + +QUnit.test("CircularBuffer - Write test", function (assert) +{ + var buffer = new ds.CircularBuffer(10); + buffer.write(0); + buffer.write(0); + buffer.write(0); + buffer.write(0); + for (var i = 0; i < 4; i++) + assert.deepEqual(buffer.read(i), 0, "Write 0"); + for (var j = 4; j < 10; j++) + assert.deepEqual(buffer.read(j), undefined, "Write 0"); + buffer.write(1); + buffer.write(1); + buffer.write(1); + buffer.write(1); + buffer.write(1); + buffer.write(1); + buffer.write(1); + buffer.write(1); + for (var m = 4; m < 12; m++) + assert.deepEqual(buffer.read(m), 1, "Write 1"); + for (var n = 2; n < 4; n++) + assert.deepEqual(buffer.read(n), 0, "Write 1"); + assert.deepEqual(buffer.isFull(), true, "Is full"); +}); + +QUnit.test("CircularBuffer - Free test", function (assert) +{ + var buffer = new ds.CircularBuffer(10); + for (var k = 0; k < 12; k++) + buffer.write(k); + buffer.free(2, 8); + for (var i = 2; i < 8; i++) + assert.deepEqual(buffer.read(i), undefined, "Free 2...8"); + assert.deepEqual(buffer.head, 2, "Free 2...8"); + assert.deepEqual(buffer.tail, 8, "Free 2...8"); + + for (var l = 0; l < 12; l++) + buffer.write(l); + assert.deepEqual(buffer.head, 4, "Write 12 items"); + assert.deepEqual(buffer.tail, 4, "Write 12 items"); + + buffer.free(8, 6); + for (var m = 8; m < 6; m = (m + 1) % 10) + assert.deepEqual(buffer.read(m), undefined, "Free 8...6"); + assert.deepEqual(buffer.head, 8, "Free 8...6"); + assert.deepEqual(buffer.tail, 6, "Free 8...6"); + + buffer.freeAll(); + for (var j = 0; j < 10; j++) + assert.deepEqual(buffer.read(j), undefined, "Free all"); + assert.deepEqual(buffer.isEmpty(), true, "Is empty"); +}); + +QUnit.test("CircularBuffer - Empty test", function (assert) +{ + var buffer = new ds.CircularBuffer(10); + buffer.write(0); + buffer.write(0); + buffer.write(0); + assert.deepEqual(buffer.isEmpty(), false, "Is not empty"); + buffer.free(0, 8); + assert.deepEqual(buffer.isEmpty(), true, "Is empty"); +}); + +QUnit.test("CircularBuffer - Clone test", function (assert) +{ + var buffer = new ds.CircularBuffer(10); + for (var i = 0; i < 15; i++) + buffer.write(i); + var clone = buffer.clone(); + for (var j = 0; j < 9; j++) + assert.deepEqual(clone.read(j), buffer.read(j), "Check items"); + assert.deepEqual(clone.head, buffer.head, "Check head position"); + assert.deepEqual(clone.tail, buffer.tail, "Check tail position"); + assert.deepEqual(clone.isEmpty(), buffer.isEmpty(), "Check empty"); + assert.deepEqual(clone.isFull(), buffer.isFull(), "Check empty"); +}); + +QUnit.test("CircularBuffer - Resize test", function (assert) +{ + var buffer = new ds.CircularBuffer(5); + for (var i = 0; i < 8; i++) + buffer.write(i); + var clone = buffer.clone(); + buffer.resize(10); + assert.deepEqual(buffer.head, 8, "Check head position"); + assert.deepEqual(buffer.tail, 3, "Check tail position"); + for (var j = 0; j < 10; j++) + if (j < 3 || j > 7) + assert.deepEqual(buffer.read(j), undefined, "Increase size"); + else + assert.deepEqual(buffer.read(j), j, "Augment resize"); + buffer = clone; + buffer.resize(3); + assert.deepEqual(buffer.head, 0, "Check head position"); + assert.deepEqual(buffer.tail, 0, "Check tail position"); + for (var k = 0; k < 3; k++) + assert.deepEqual(buffer.read(k), k + 3, "Decrease size"); +}); + +QUnit.test("CircularBuffer - Iterator test", function (assert) +{ + var buffer = new ds.CircularBuffer(10); + var it = buffer.getIterator(); + it.first(); + assert.deepEqual(it.isDone(), true, "Check empty buffer iterator"); + buffer.write(0); + buffer.write(0); + buffer.write(0); + buffer.write(0); + buffer.write(1); + buffer.write(1); + buffer.write(1); + buffer.write(1); + buffer.write(1); + buffer.write(1); + buffer.write(1); + buffer.write(1); + var result = [0, 0, 1, 1, 1, 1, 1, 1, 1, 1]; + var i = 0; + for (it.first(); !it.isDone(); it.next(), i++) + assert.deepEqual(it.getItem(), result[i], "Check iterator"); +}); \ No newline at end of file diff --git a/Tests/DoubleLinkedList_Test.js b/Tests/DoubleLinkedList_Test.js deleted file mode 100644 index 7e7fb45..0000000 --- a/Tests/DoubleLinkedList_Test.js +++ /dev/null @@ -1,420 +0,0 @@ -/** - * Created by Stefano on 31/03/14. - */ - -test("DoubleLinkedList - Init test", function () { - var list = new DoubleLinkedList(0, 1, 2); - deepEqual(list.toArray(), [0, 1, 2], "Init list"); - list = new DoubleLinkedList(2); - deepEqual(list.toArray(), [2], "Init list"); -}); - -test("DoubleLinkedList - Init range test", function () { - var list = new DoubleLinkedList(Range(0, 2)); - deepEqual(list.toArray(), [0, 1, 2], "Init list"); - list = new DoubleLinkedList(Range(2, -2, -0.5)); - deepEqual(list.toArray(), [2, 1.5, 1, 0.5, 0, -0.5, -1, -1.5, -2], "Init list"); -}); - -test("DoubleLinkedList - Push test", function () { - var list = new DoubleLinkedList(); - list.pushFront(0); - list.pushFront(1); - list.pushBack(2); - list.pushBack(3); - deepEqual(list.getItem(0), 1, "Push front 1"); - deepEqual(list.getItem(1), 0, "Push front 0"); - deepEqual(list.getItem(2), 2, "Push back 2"); - deepEqual(list.getItem(3), 3, "Push back 3"); -}); - -test("DoubleLinkedList - Pop test", function () { - var list = new DoubleLinkedList(); - list.pushFront(0); - list.pushFront(1); - list.pushBack(2); - list.pushBack(3); - deepEqual(list.popBack(), 3, "Pop back 3"); - deepEqual(list.popFront(), 1, "Pop front 1"); - deepEqual(list.popBack(), 2, "Pop back 2"); - deepEqual(list.popFront(), 0, "Pop front 0"); -}); - -test("DoubleLinkedList - Remove at test", function () { - var list = new DoubleLinkedList(); - list.pushFront(0); - list.pushFront(1); - list.pushBack(2); - list.pushBack(3); - deepEqual(list.removeAt(1), 0, "Remove at 1"); - deepEqual(list.removeAt(1), 2, "Remove at 1"); - deepEqual(list.removeAt(1), 3, "Remove at 1"); - deepEqual(list.removeAt(0), 1, "Remove at 0"); -}); - -test("DoubleLinkedList - Remove test", function () { - var list = new DoubleLinkedList(); - for (var i = 0; i < 30; i++) - list.pushBack(i % 10); - list.pushBack(15); - var callback = function (item) { - return !(item % 2) && item > 5; - }; - list.remove(0); - deepEqual(list.indexOf(0), 9, "Remove 0"); - list.remove(15); - deepEqual(list.indexOf(15), -1, "Remove 15"); - list.remove(9); - list.remove(9); - list.remove(9); - deepEqual(list.indexOf(9), -1, "Remove 9"); - list.remove(0, callback); - deepEqual(list.indexOf(6), 13, "Remove the first even numbers greater than 5"); -}); - -test("DoubleLinkedList - Remove all test", function () { - var list = new DoubleLinkedList(); - for (var i = 0; i < 30; i++) - list.pushBack(i % 10); - var callback = function (item) { - return !(item % 2) && item > 5; - }; - list.removeAll(0); - deepEqual(list.indexOf(0), -1, "Remove all 0"); - list.removeAll(9); - deepEqual(list.indexOf(9), -1, "Remove all 9"); - list.removeAll(0, callback); - deepEqual(list.indexOf(8), -1, "Remove all the even numbers greater than 5"); -}); - -test("DoubleLinkedList - Remove segment test", function () { - var list = new DoubleLinkedList(); - for (var i = 0; i < 10; i++) - list.pushBack(i); - deepEqual(list.removeSegment(2, 6), [2, 3, 4, 5, 6], "Remove the segment from the list"); - deepEqual(list.toArray(), [0, 1, 7, 8, 9], "Remove the segment from the list"); - deepEqual(list.getLength(), 5, "Remove the segment from the list"); - deepEqual(list.removeSegment(2, 1), [7, 8, 9], "Remove the segment from the list"); - deepEqual(list.toArray(), [0, 1], "Remove the segment from the list"); - deepEqual(list.getLength(), 2, "Remove the segment from the list"); -}); - -test("DoubleLinkedList - Modify at test", function () { - var list = new DoubleLinkedList(); - for (var i = 0; i < 4; i++) - list.pushBack(i); - list.modifyAt(2, 6); - deepEqual(list.toArray(), [0, 1, 6, 3], "Change at valid position"); - list.modifyAt(5, 5); - deepEqual(list.toArray(), [0, 1, 6, 3], "Change at non valid position"); -}); - -test("DoubleLinkedList - Delete node test", function () { - var list = new DoubleLinkedList(); - list.pushFront(0); - list.pushFront(1); - list.pushBack(2); - list.pushBack(3); - var it = list.getIterator(); - for (it.first(); !it.isDone(); it.next()) - if (it.getItem()) - list.deleteNode(it.getNode()); - deepEqual(list.getItem(0), 0, "Delete node"); -}); - -test("DoubleLinkedList - Sort test", function () { - var list = new DoubleLinkedList(); - const length = 100; - for (var i = 0; i < length; i++) - list.pushFront(i); - - list.sort(); - deepEqual(list.getItem(0), 0, "Sort"); - deepEqual(list.getItem(length - 1), length - 1, "Sort"); -}); - -test("DoubleLinkedList - Sort with callback test", function () { - var list = new DoubleLinkedList(); - const length = 100; - - for (var i = 0; i < length; i++) - list.pushFront(i); - - list.sort( - function (item) { - return -item; - } - ); - deepEqual(list.getItem(0), length - 1, "Sort with callback"); - deepEqual(list.getItem(length - 1), 0, "Sort with callback"); -}); - -test("DoubleLinkedList - Filter test", function () { - var list = new DoubleLinkedList(); - const length = 100; - - for (var i = 0; i < length; i++) - list.pushFront(i); - - var result = list.filter(function (item) { - return 1 - item % 2; - }); - - deepEqual(result[0], 98, "Filter of the even values"); - deepEqual(result[result.length - 1], 0, "Filter on the even values"); -}); - -test("DoubleLinkedList - Reverse test", function () { - var list = new DoubleLinkedList(); - const length = 100; - - for (var i = 0; i < length; i++) - list.pushFront(i); - - list.reverse(); - - deepEqual(list.getItem(0), 0, "Reverse"); - deepEqual(list.getItem(length - 1), 99, "Reverse"); -}); - -test("DoubleLinkedList - Iterator test", function () { - var list = new DoubleLinkedList(); - - for (var i = 0; i < 100; i++) - list.pushBack(i); - - var it = list.getIterator(); - - var j = 0; - for (it.first(); !it.isDone(); it.next(), j++) { - deepEqual(it.getItem(), j, "Check iterator position"); - } - for (it.last(); !it.isDone(); it.previous(), j--) { - deepEqual(it.getItem(), j - 1, "Check iterator position"); - } - -}); - -test("DoubleLinkedList - Add at test", function () { - var list = new DoubleLinkedList(); - list.addAt(5, 0); - deepEqual(list.peek(), 5, "Add at 0"); - list.addAt(2, 1); - deepEqual(list.getItem(1), 2, "Add at 1"); - list.addAt(15, 6); - deepEqual(list.getItem(2), undefined, "Add at 6"); - deepEqual(list.getItem(5), undefined, "Add at 6"); - deepEqual(list.getItem(6), 15, "Add at 6"); - list.addAt(30, 6); - deepEqual(list.getItem(6), 30, "Add at 6"); - deepEqual(list.getItem(7), 15, "Add at 6"); - list.addAt(6, 0); - deepEqual(list.peek(), 6, "Add at 0"); -}); - -test("DoubleLinkedList - MultiPop test", function () { - var list = new DoubleLinkedList(); - list.pushFront(0); - list.pushFront(1); - list.pushBack(2); - list.pushBack(3); - deepEqual(list.multiPopBack(2), [3, 2], "Multi pop back"); - deepEqual(list.multiPopFront(2), [1, 0], "Multi pop front"); -}); - -test("DoubleLinkedList - Get length test", function () { - var list = new DoubleLinkedList(); - deepEqual(list.getLength(), 0, "Get length empty"); - list.pushFront(0); - list.pushFront(1); - list.pushBack(2); - list.pushBack(3); - deepEqual(list.getLength(), 4, "Get length"); - list.multiPopBack(2); - deepEqual(list.getLength(), 2, "Get length"); - -}); - -test("DoubleLinkedList - Peek test", function () { - var list = new DoubleLinkedList(); - list.pushFront(0); - deepEqual(list.peek(), 0, "Peek"); - list.pushFront(1); - list.pushBack(2); - deepEqual(list.peek(), 1, "Peek"); - list.pushBack(3); - deepEqual(list.peek(), 1, "Peek"); -}); - -test("DoubleLinkedList - Clear test", function () { - var list = new DoubleLinkedList(); - list.pushFront(0); - list.pushFront(1); - list.pushBack(2); - list.pushBack(3); - list.clear(); - deepEqual(list.getLength(), 0, "Clear the list"); - -}); - -test("DoubleLinkedList - Is empty test", function () { - var list = new DoubleLinkedList(); - deepEqual(list.isEmpty(), true, "Is empty"); - list.pushFront(0); - list.pushFront(1); - list.pushBack(2); - list.pushBack(3); - deepEqual(list.isEmpty(), false, "Is not empty"); - list.clear(); - deepEqual(list.isEmpty(), true, "Is empty"); -}); - -test("DoubleLinkedList - contains", function () { - var list = new DoubleLinkedList(); - list.pushBack(0); - list.pushBack(2); - deepEqual(list.contains(0), true, "Contains 0"); - deepEqual(list.contains(2), true, "Contains 2"); - deepEqual(list.contains(1), false, "Not contains 1"); - var callback = function (item) { - return item > 0; - }; - deepEqual(list.contains(null, callback), true, "Contains a value > 0"); - callback = function (item) { - return item < 0; - }; - deepEqual(list.contains(null, callback), false, "Contains a value < 0"); -}); - -test("DoubleLinkedList - execute", function () { - var list = new DoubleLinkedList(); - list.pushBack(0); - list.pushBack(2); - var callback = function (item) { - return item * 2; - }; - list.execute(callback); - deepEqual(list.getItem(0), 0, "Execute for item 0"); - deepEqual(list.getItem(1), 4, "Execute for item 1"); -}); - -test("DoubleLinkedList - Index of test", function () { - var list = new DoubleLinkedList(); - for (var i = 0; i < 10; i++) - list.pushBack(i); - var callback = function (item) { - return !(item % 2) && item > 5; - }; - deepEqual(list.indexOf(0), 0, "Index of 0"); - deepEqual(list.indexOf(15), -1, "Index of 15"); - deepEqual(list.indexOf(5), 5, "Index of 5"); - list.removeAt(5); - deepEqual(list.indexOf(6), 5, "Index of 6"); - deepEqual(list.indexOf(null, callback), 5, "Index of the first even number greater than 5"); -}); - -test("DoubleLinkedList - Last index of test", function () { - var list = new DoubleLinkedList(); - for (var i = 0; i < 10; i++) - list.pushBack(i); - var callback = function (item) { - return !(item % 2) && item > 5; - }; - deepEqual(list.lastIndexOf(0), 0, "Last index of 0"); - deepEqual(list.lastIndexOf(15), -1, "Last index of 15"); - deepEqual(list.lastIndexOf(5), 5, "Last index of 5"); - list.removeAt(5); - deepEqual(list.lastIndexOf(6), 5, "Last index of 6"); - deepEqual(list.lastIndexOf(null, callback), 7, "Index of the last even number greater than 5"); -}); - -test("DoubleLinkedList - Indexes of test", function () { - var list = new DoubleLinkedList(); - for (var i = 0; i < 30; i++) - list.pushBack(i % 10); - var callback = function (item) { - return !(item % 2) && item > 5; - }; - deepEqual(list.allIndexesOf(0), [0, 10, 20], "Indexes of 0"); - deepEqual(list.allIndexesOf(15), [], "Indexes of 15"); - deepEqual(list.allIndexesOf(5), [5, 15, 25], "Indexes of 5"); - list.removeAt(5); - deepEqual(list.allIndexesOf(5), [14, 24], "Indexes of 5"); - deepEqual(list.allIndexesOf(6), [5, 15, 25], "Indexes of 6"); - deepEqual(list.allIndexesOf(null, callback), [5, 7, 15, 17, 25, 27], "Indexes of the even numbers greater than 5"); -}); - -test("DoubleLinkedList - Join test", function () { - var listA = new DoubleLinkedList(); - var listB = new DoubleLinkedList(); - for (var i = 0; i < 5; i++) { - listA.pushBack(i); - listB.pushBack(i); - } - listA.join(listB); - deepEqual(listA.allIndexesOf(3), [3, 8], "Join of the lists"); - deepEqual(listA.getLength(), 10, "Check the length of the list"); -}); - -test("DoubleLinkedList - Divide test", function () { - var list = new DoubleLinkedList(); - for (var i = 0; i < 10; i++) - list.pushBack(i); - var listA = list.divide(-1); - deepEqual(listA.isEmpty(), true, "Divide before start"); - var listB = list.divide(10); - deepEqual(listB.isEmpty(), true, "Divide after end"); - var listC = list.divide(8); - deepEqual(listC.getItem(0), 8, "Divide at valid position"); - deepEqual(listC.getItem(1), 9, "Divide at valid position"); - deepEqual(listC.getLength(), 2, "Divide at valid position"); - deepEqual(list.getItem(8), undefined, "Divide at valid position"); - deepEqual(list.getLength(), 8, "Divide at valid position"); - var listD = list.divide(0); - deepEqual(listD.getLength(), 8, "Divide at the first position"); - deepEqual(listD.getItem(0), 0, "Divide at the first position"); - deepEqual(listD.getItem(8), undefined, "Divide at the first position"); - deepEqual(listD.getItem(7), 7, "Divide at the first position"); - deepEqual(list.getLength(), 0, "Divide at the first position"); - deepEqual(list.getItem(0), undefined, "Divide at the first position"); -}); - -test("DoubleLinkedList - Clone test", function () { - var list = new DoubleLinkedList(); - for (var i = 0; i < 10; i++) - list.pushBack(i); - var clone = list.clone(); - var it = clone.getIterator(); - var j = 0; - for (it.first(); !it.isDone(); it.next(), j++) - deepEqual(it.getItem(), j, "Clone of the list"); -}); - -test("DoubleLinkedList - Clone distinct test", function () { - var list = new DoubleLinkedList(); - for (var i = 0; i < 20; i++) - list.pushBack(i % 10); - var clone = list.cloneDistinct(); - deepEqual(clone.allIndexesOf(2), [2], "Clone of the list"); -}); - -test("DoubleLinkedList - Split test", function () { - var list = new DoubleLinkedList(); - for (var i = 0; i < 7; i++) - list.pushBack(i); - var lists = list.split(3); - deepEqual(lists.length, 3, "Check the number of lists created"); - deepEqual(lists[0].toArray(), [0, 1, 2], "Check the items in the lists created"); - deepEqual(lists[1].toArray(), [3, 4, 5], "Check the items in the lists created"); - deepEqual(lists[2].toArray(), [6], "Check the items in the lists created"); -}); - -test("DoubleLinkedList - Count test", function () { - var list = new DoubleLinkedList(); - for (var i = 0; i < 10; i++) - list.pushBack(i); - var callback = function (item) { - return item > 4; - }; - deepEqual(list.count(callback), 5, "Count the items that are greater than 4"); -}); \ No newline at end of file diff --git a/Tests/DoubleLinkedList_Test.ts b/Tests/DoubleLinkedList_Test.ts new file mode 100644 index 0000000..bd8c409 --- /dev/null +++ b/Tests/DoubleLinkedList_Test.ts @@ -0,0 +1,466 @@ +/** + * Created by Stefano on 31/03/14. + */ + +QUnit.test("DoubleLinkedList - Init test", function (assert) +{ + var list = new ds.DoubleLinkedList(0, 1, 2); + assert.deepEqual(list.toArray(), [0, 1, 2], "Init list"); + list = new ds.DoubleLinkedList(2); + assert.deepEqual(list.toArray(), [2], "Init list"); +}); + +QUnit.test("DoubleLinkedList - Init range test", function (assert) +{ + var list = new ds.DoubleLinkedList(ds.Range(0, 2)); + assert.deepEqual(list.toArray(), [0, 1, 2], "Init list"); + list = new ds.DoubleLinkedList(ds.Range(2, -2, -0.5)); + assert.deepEqual(list.toArray(), [2, 1.5, 1, 0.5, 0, -0.5, -1, -1.5, -2], "Init list"); +}); + +QUnit.test("DoubleLinkedList - Push test", function (assert) +{ + var list = new ds.DoubleLinkedList(); + list.pushFront(0); + list.pushFront(1); + list.pushBack(2); + list.pushBack(3); + assert.deepEqual(list.getItem(0), 1, "Push front 1"); + assert.deepEqual(list.getItem(1), 0, "Push front 0"); + assert.deepEqual(list.getItem(2), 2, "Push back 2"); + assert.deepEqual(list.getItem(3), 3, "Push back 3"); +}); + +QUnit.test("DoubleLinkedList - Pop test", function (assert) +{ + var list = new ds.DoubleLinkedList(); + list.pushFront(0); + list.pushFront(1); + list.pushBack(2); + list.pushBack(3); + assert.deepEqual(list.popBack(), 3, "Pop back 3"); + assert.deepEqual(list.popFront(), 1, "Pop front 1"); + assert.deepEqual(list.popBack(), 2, "Pop back 2"); + assert.deepEqual(list.popFront(), 0, "Pop front 0"); +}); + +QUnit.test("DoubleLinkedList - Remove at test", function (assert) +{ + var list = new ds.DoubleLinkedList(); + list.pushFront(0); + list.pushFront(1); + list.pushBack(2); + list.pushBack(3); + assert.deepEqual(list.removeAt(1), 0, "Remove at 1"); + assert.deepEqual(list.removeAt(1), 2, "Remove at 1"); + assert.deepEqual(list.removeAt(1), 3, "Remove at 1"); + assert.deepEqual(list.removeAt(0), 1, "Remove at 0"); +}); + +QUnit.test("DoubleLinkedList - Remove test", function (assert) +{ + var list = new ds.DoubleLinkedList(); + for (var i = 0; i < 30; i++) + list.pushBack(i % 10); + list.pushBack(15); + var callback = function (item) + { + return !(item % 2) && item > 5; + }; + list.remove(0); + assert.deepEqual(list.indexOf(0), 9, "Remove 0"); + list.remove(15); + assert.deepEqual(list.indexOf(15), -1, "Remove 15"); + list.remove(9); + list.remove(9); + list.remove(9); + assert.deepEqual(list.indexOf(9), -1, "Remove 9"); + list.remove(0, callback); + assert.deepEqual(list.indexOf(6), 13, "Remove the first even numbers greater than 5"); +}); + +QUnit.test("DoubleLinkedList - Remove all test", function (assert) +{ + var list = new ds.DoubleLinkedList(); + for (var i = 0; i < 30; i++) + list.pushBack(i % 10); + var callback = function (item) + { + return !(item % 2) && item > 5; + }; + list.removeAll(0); + assert.deepEqual(list.indexOf(0), -1, "Remove all 0"); + list.removeAll(9); + assert.deepEqual(list.indexOf(9), -1, "Remove all 9"); + list.removeAll(0, callback); + assert.deepEqual(list.indexOf(8), -1, "Remove all the even numbers greater than 5"); +}); + +QUnit.test("DoubleLinkedList - Remove segment test", function (assert) +{ + var list = new ds.DoubleLinkedList(); + for (var i = 0; i < 10; i++) + list.pushBack(i); + assert.deepEqual(list.removeSegment(2, 6), [2, 3, 4, 5, 6], "Remove the segment from the list"); + assert.deepEqual(list.toArray(), [0, 1, 7, 8, 9], "Remove the segment from the list"); + assert.deepEqual(list.getLength(), 5, "Remove the segment from the list"); + assert.deepEqual(list.removeSegment(2, 1), [7, 8, 9], "Remove the segment from the list"); + assert.deepEqual(list.toArray(), [0, 1], "Remove the segment from the list"); + assert.deepEqual(list.getLength(), 2, "Remove the segment from the list"); +}); + +QUnit.test("DoubleLinkedList - Modify at test", function (assert) +{ + var list = new ds.DoubleLinkedList(); + for (var i = 0; i < 4; i++) + list.pushBack(i); + list.modifyAt(2, 6); + assert.deepEqual(list.toArray(), [0, 1, 6, 3], "Change at valid position"); + list.modifyAt(5, 5); + assert.deepEqual(list.toArray(), [0, 1, 6, 3], "Change at non valid position"); +}); + +QUnit.test("DoubleLinkedList - Delete node test", function (assert) +{ + var list = new ds.DoubleLinkedList(); + list.pushFront(0); + list.pushFront(1); + list.pushBack(2); + list.pushBack(3); + var it = list.getIterator(); + for (it.first(); !it.isDone(); it.next()) + if (it.getItem()) + list.deleteNode(it.getNode()); + assert.deepEqual(list.getItem(0), 0, "Delete node"); +}); + +QUnit.test("DoubleLinkedList - Sort test", function (assert) +{ + var list = new ds.DoubleLinkedList(); + const length = 100; + for (var i = 0; i < length; i++) + list.pushFront(i); + + list.sort(); + assert.deepEqual(list.getItem(0), 0, "Sort"); + assert.deepEqual(list.getItem(length - 1), length - 1, "Sort"); +}); + +QUnit.test("DoubleLinkedList - Sort with callback test", function (assert) +{ + var list = new ds.DoubleLinkedList(); + const length = 100; + + for (var i = 0; i < length; i++) + list.pushFront(i); + + list.sort( + function (item) + { + return -item; + } + ); + assert.deepEqual(list.getItem(0), length - 1, "Sort with callback"); + assert.deepEqual(list.getItem(length - 1), 0, "Sort with callback"); +}); + +QUnit.test("DoubleLinkedList - Filter test", function (assert) +{ + var list = new ds.DoubleLinkedList(); + const length = 100; + + for (var i = 0; i < length; i++) + list.pushFront(i); + + var result = list.filter(function (item) + { + return Boolean(1 - item % 2); + }); + + assert.deepEqual(result[0], 98, "Filter of the even values"); + assert.deepEqual(result[result.length - 1], 0, "Filter on the even values"); +}); + +QUnit.test("DoubleLinkedList - Reverse test", function (assert) +{ + var list = new ds.DoubleLinkedList(); + const length = 100; + + for (var i = 0; i < length; i++) + list.pushFront(i); + + list.reverse(); + + assert.deepEqual(list.getItem(0), 0, "Reverse"); + assert.deepEqual(list.getItem(length - 1), 99, "Reverse"); +}); + +QUnit.test("DoubleLinkedList - Iterator test", function (assert) +{ + var list = new ds.DoubleLinkedList(); + + for (var i = 0; i < 100; i++) + list.pushBack(i); + + var it = list.getIterator(); + + var j = 0; + for (it.first(); !it.isDone(); it.next(), j++) + { + assert.deepEqual(it.getItem(), j, "Check iterator position"); + } + for (it.last(); !it.isDone(); it.previous(), j--) + { + assert.deepEqual(it.getItem(), j - 1, "Check iterator position"); + } + +}); + +QUnit.test("DoubleLinkedList - Add at test", function (assert) +{ + var list = new ds.DoubleLinkedList(); + list.addAt(5, 0); + assert.deepEqual(list.peek(), 5, "Add at 0"); + list.addAt(2, 1); + assert.deepEqual(list.getItem(1), 2, "Add at 1"); + list.addAt(15, 6); + assert.deepEqual(list.getItem(2), undefined, "Add at 6"); + assert.deepEqual(list.getItem(5), undefined, "Add at 6"); + assert.deepEqual(list.getItem(6), 15, "Add at 6"); + list.addAt(30, 6); + assert.deepEqual(list.getItem(6), 30, "Add at 6"); + assert.deepEqual(list.getItem(7), 15, "Add at 6"); + list.addAt(6, 0); + assert.deepEqual(list.peek(), 6, "Add at 0"); +}); + +QUnit.test("DoubleLinkedList - MultiPop test", function (assert) +{ + var list = new ds.DoubleLinkedList(); + list.pushFront(0); + list.pushFront(1); + list.pushBack(2); + list.pushBack(3); + assert.deepEqual(list.multiPopBack(2), [3, 2], "Multi pop back"); + assert.deepEqual(list.multiPopFront(2), [1, 0], "Multi pop front"); +}); + +QUnit.test("DoubleLinkedList - Get length test", function (assert) +{ + var list = new ds.DoubleLinkedList(); + assert.deepEqual(list.getLength(), 0, "Get length empty"); + list.pushFront(0); + list.pushFront(1); + list.pushBack(2); + list.pushBack(3); + assert.deepEqual(list.getLength(), 4, "Get length"); + list.multiPopBack(2); + assert.deepEqual(list.getLength(), 2, "Get length"); + +}); + +QUnit.test("DoubleLinkedList - Peek test", function (assert) +{ + var list = new ds.DoubleLinkedList(); + list.pushFront(0); + assert.deepEqual(list.peek(), 0, "Peek"); + list.pushFront(1); + list.pushBack(2); + assert.deepEqual(list.peek(), 1, "Peek"); + list.pushBack(3); + assert.deepEqual(list.peek(), 1, "Peek"); +}); + +QUnit.test("DoubleLinkedList - Clear test", function (assert) +{ + var list = new ds.DoubleLinkedList(); + list.pushFront(0); + list.pushFront(1); + list.pushBack(2); + list.pushBack(3); + list.clear(); + assert.deepEqual(list.getLength(), 0, "Clear the list"); + +}); + +QUnit.test("DoubleLinkedList - Is empty test", function (assert) +{ + var list = new ds.DoubleLinkedList(); + assert.deepEqual(list.isEmpty(), true, "Is empty"); + list.pushFront(0); + list.pushFront(1); + list.pushBack(2); + list.pushBack(3); + assert.deepEqual(list.isEmpty(), false, "Is not empty"); + list.clear(); + assert.deepEqual(list.isEmpty(), true, "Is empty"); +}); + +QUnit.test("DoubleLinkedList - contains", function (assert) +{ + var list = new ds.DoubleLinkedList(); + list.pushBack(0); + list.pushBack(2); + assert.deepEqual(list.contains(0), true, "Contains 0"); + assert.deepEqual(list.contains(2), true, "Contains 2"); + assert.deepEqual(list.contains(1), false, "Not contains 1"); + var callback = function (item) + { + return item > 0; + }; + assert.deepEqual(list.contains(null, callback), true, "Contains a value > 0"); + callback = function (item) + { + return item < 0; + }; + assert.deepEqual(list.contains(null, callback), false, "Contains a value < 0"); +}); + +QUnit.test("DoubleLinkedList - execute", function (assert) +{ + var list = new ds.DoubleLinkedList(); + list.pushBack(0); + list.pushBack(2); + var callback = function (item) + { + return item * 2; + }; + list.execute(callback); + assert.deepEqual(list.getItem(0), 0, "Execute for item 0"); + assert.deepEqual(list.getItem(1), 4, "Execute for item 1"); +}); + +QUnit.test("DoubleLinkedList - Index of test", function (assert) +{ + var list = new ds.DoubleLinkedList(); + for (var i = 0; i < 10; i++) + list.pushBack(i); + var callback = function (item) + { + return !(item % 2) && item > 5; + }; + assert.deepEqual(list.indexOf(0), 0, "Index of 0"); + assert.deepEqual(list.indexOf(15), -1, "Index of 15"); + assert.deepEqual(list.indexOf(5), 5, "Index of 5"); + list.removeAt(5); + assert.deepEqual(list.indexOf(6), 5, "Index of 6"); + assert.deepEqual(list.indexOf(null, callback), 5, "Index of the first even number greater than 5"); +}); + +QUnit.test("DoubleLinkedList - Last index of test", function (assert) +{ + var list = new ds.DoubleLinkedList(); + for (var i = 0; i < 10; i++) + list.pushBack(i); + var callback = function (item) + { + return !(item % 2) && item > 5; + }; + assert.deepEqual(list.lastIndexOf(0), 0, "Last index of 0"); + assert.deepEqual(list.lastIndexOf(15), -1, "Last index of 15"); + assert.deepEqual(list.lastIndexOf(5), 5, "Last index of 5"); + list.removeAt(5); + assert.deepEqual(list.lastIndexOf(6), 5, "Last index of 6"); + assert.deepEqual(list.lastIndexOf(null, callback), 7, "Index of the last even number greater than 5"); +}); + +QUnit.test("DoubleLinkedList - Indexes of test", function (assert) +{ + var list = new ds.DoubleLinkedList(); + for (var i = 0; i < 30; i++) + list.pushBack(i % 10); + var callback = function (item) + { + return !(item % 2) && item > 5; + }; + assert.deepEqual(list.allIndexesOf(0), [0, 10, 20], "Indexes of 0"); + assert.deepEqual(list.allIndexesOf(15), [], "Indexes of 15"); + assert.deepEqual(list.allIndexesOf(5), [5, 15, 25], "Indexes of 5"); + list.removeAt(5); + assert.deepEqual(list.allIndexesOf(5), [14, 24], "Indexes of 5"); + assert.deepEqual(list.allIndexesOf(6), [5, 15, 25], "Indexes of 6"); + assert.deepEqual(list.allIndexesOf(null, callback), [5, 7, 15, 17, 25, 27], "Indexes of the even numbers greater than 5"); +}); + +QUnit.test("DoubleLinkedList - Join test", function (assert) +{ + var listA = new ds.DoubleLinkedList(); + var listB = new ds.DoubleLinkedList(); + for (var i = 0; i < 5; i++) + { + listA.pushBack(i); + listB.pushBack(i); + } + listA.join(listB); + assert.deepEqual(listA.allIndexesOf(3), [3, 8], "Join of the lists"); + assert.deepEqual(listA.getLength(), 10, "Check the length of the list"); +}); + +QUnit.test("DoubleLinkedList - Divide test", function (assert) +{ + var list = new ds.DoubleLinkedList(); + for (var i = 0; i < 10; i++) + list.pushBack(i); + var listA = list.divide(-1); + assert.deepEqual(listA.isEmpty(), true, "Divide before start"); + var listB = list.divide(10); + assert.deepEqual(listB.isEmpty(), true, "Divide after end"); + var listC = list.divide(8); + assert.deepEqual(listC.getItem(0), 8, "Divide at valid position"); + assert.deepEqual(listC.getItem(1), 9, "Divide at valid position"); + assert.deepEqual(listC.getLength(), 2, "Divide at valid position"); + assert.deepEqual(list.getItem(8), undefined, "Divide at valid position"); + assert.deepEqual(list.getLength(), 8, "Divide at valid position"); + var listD = list.divide(0); + assert.deepEqual(listD.getLength(), 8, "Divide at the first position"); + assert.deepEqual(listD.getItem(0), 0, "Divide at the first position"); + assert.deepEqual(listD.getItem(8), undefined, "Divide at the first position"); + assert.deepEqual(listD.getItem(7), 7, "Divide at the first position"); + assert.deepEqual(list.getLength(), 0, "Divide at the first position"); + assert.deepEqual(list.getItem(0), undefined, "Divide at the first position"); +}); + +QUnit.test("DoubleLinkedList - Clone test", function (assert) +{ + var list = new ds.DoubleLinkedList(); + for (var i = 0; i < 10; i++) + list.pushBack(i); + var clone = list.clone(); + var it = clone.getIterator(); + var j = 0; + for (it.first(); !it.isDone(); it.next(), j++) + assert.deepEqual(it.getItem(), j, "Clone of the list"); +}); + +QUnit.test("DoubleLinkedList - Clone distinct test", function (assert) +{ + var list = new ds.DoubleLinkedList(); + for (var i = 0; i < 20; i++) + list.pushBack(i % 10); + var clone = list.cloneDistinct(); + assert.deepEqual(clone.allIndexesOf(2), [2], "Clone of the list"); +}); + +QUnit.test("DoubleLinkedList - Split test", function (assert) +{ + var list = new ds.DoubleLinkedList(); + for (var i = 0; i < 7; i++) + list.pushBack(i); + var lists = list.split(3); + assert.deepEqual(lists.length, 3, "Check the number of lists created"); + assert.deepEqual(lists[0].toArray(), [0, 1, 2], "Check the items in the lists created"); + assert.deepEqual(lists[1].toArray(), [3, 4, 5], "Check the items in the lists created"); + assert.deepEqual(lists[2].toArray(), [6], "Check the items in the lists created"); +}); + +QUnit.test("DoubleLinkedList - Count test", function (assert) +{ + var list = new ds.DoubleLinkedList(); + for (var i = 0; i < 10; i++) + list.pushBack(i); + var callback = function (item) + { + return item > 4; + }; + assert.deepEqual(list.count(callback), 5, "Count the items that are greater than 4"); +}); \ No newline at end of file diff --git a/Tests/HashTable_Test.js b/Tests/HashTable_Test.js deleted file mode 100644 index 4605f18..0000000 --- a/Tests/HashTable_Test.js +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Created by Stefano on 31/03/14. - */ - -test("HashTable - Insert test", function () { - var table = new HashTable(4); - for (var i = 0; i < 20; i++) - table.insert(i, "Insert # " + i); - for (var j = 0; j < 20; j++) - deepEqual(table.search(j), "Insert # " + j, "Insert " + j); -}); - -test("HashTable - Delete key test", function () { - var table = new HashTable(4); - for (var i = 0; i < 20; i++) - table.insert(i, i); - table.deleteKey(6); - deepEqual(table.search(6), undefined, "Delete key"); -}); - -test("HashTable - Delete all key test", function () { - var table = new HashTable(4); - for (var i = 0; i < 100; i++) - table.insert(i % 20, {value: i % 20}); - table.deleteAllKey(13); - deepEqual(table.searchAll(13).length, 0, "Delete all key"); -}); - -test("HashTable - Get keys test", function () { - var table = new HashTable(50); - var keys = []; - for (var i = 0; i < 100; i++) { - table.insert(i, {value: i % 20}); - keys.push(i); - } - keys.sort(); - var storedKeys = table.getKeys().sort(); - deepEqual(storedKeys, keys, "Get stored keys"); -}); - -test("HashTable - Get items test", function () { - var table = new HashTable(50); - var items = []; - for (var i = 0; i < 100; i++) { - table.insert(i, i % 20); - items.push(i % 20); - } - items.sort(); - var storedKeys = table.getItems().sort(); - deepEqual(storedKeys, items, "Get stored items"); -}); - -test("HashTable - Contains key test", function () { - var table = new HashTable(50); - for (var i = 0; i < 100; i++) - table.insert(i, i % 20); - deepEqual(table.containsKey(4), true, "Contains key"); - deepEqual(table.containsKey(200), false, "Not contains key"); - var callback = function (k) { - return k > 20; - }; - deepEqual(table.containsKey(0, callback), true, "Contains key greater than 20"); - callback = function (k) { - return k < 0; - }; - deepEqual(table.containsKey(0, callback), false, "Not contains negative key"); -}); - -test("HashTable - Clear test", function () { - var table = new HashTable(50); - for (var i = 0; i < 100; i++) - table.insert(i, i % 20); - deepEqual(table.isEmpty(), false, "Before clear"); - table.clear(); - deepEqual(table.isEmpty(), true, "After clear"); -}); - -test("HashTable - Get number of keys test", function () { - var table = new HashTable(50); - deepEqual(table.getNumberOfKeys(), 0, "Before insertion"); - for (var i = 0; i < 100; i++) - table.insert(i, i % 20); - deepEqual(table.getNumberOfKeys(), 100, "After insertion"); -}); - -test("HashTable - Is empty test", function () { - var table = new HashTable(50); - deepEqual(table.isEmpty(), true, "Before insertion"); - for (var i = 0; i < 100; i++) - table.insert(i, i % 20); - deepEqual(table.isEmpty(), false, "Before clear"); - table.clear(); - deepEqual(table.isEmpty(), true, "After clear"); -}); diff --git a/Tests/HashTable_Test.ts b/Tests/HashTable_Test.ts new file mode 100644 index 0000000..11a1879 --- /dev/null +++ b/Tests/HashTable_Test.ts @@ -0,0 +1,107 @@ +/** + * Created by Stefano on 31/03/14. + */ + +QUnit.test("HashTable - Insert test", function (assert) +{ + var table = new ds.HashTable(4); + for (var i = 0; i < 20; i++) + table.insert(i, "Insert # " + i); + for (var j = 0; j < 20; j++) + assert.deepEqual(table.search(j), "Insert # " + j, "Insert " + j); +}); + +QUnit.test("HashTable - Delete key test", function (assert) +{ + var table = new ds.HashTable(4); + for (var i = 0; i < 20; i++) + table.insert(i, i); + table.deleteKey(6); + assert.deepEqual(table.search(6), undefined, "Delete key"); +}); + +QUnit.test("HashTable - Delete all key test", function (assert) +{ + var table = new ds.HashTable(4); + for (var i = 0; i < 100; i++) + table.insert(i % 20, { value: i % 20 }); + table.deleteAllKey(13); + assert.deepEqual(table.searchAll(13).length, 0, "Delete all key"); +}); + +QUnit.test("HashTable - Get keys test", function (assert) +{ + var table = new ds.HashTable(50); + var keys = []; + for (var i = 0; i < 100; i++) + { + table.insert(i, { value: i % 20 }); + keys.push(i); + } + keys.sort(); + var storedKeys = table.getKeys().sort(); + assert.deepEqual(storedKeys, keys, "Get stored keys"); +}); + +QUnit.test("HashTable - Get items test", function (assert) +{ + var table = new ds.HashTable(50); + var items = []; + for (var i = 0; i < 100; i++) + { + table.insert(i, i % 20); + items.push(i % 20); + } + items.sort(); + var storedKeys = table.getItems().sort(); + assert.deepEqual(storedKeys, items, "Get stored items"); +}); + +QUnit.test("HashTable - Contains key test", function (assert) +{ + var table = new ds.HashTable(50); + for (var i = 0; i < 100; i++) + table.insert(i, i % 20); + assert.deepEqual(table.containsKey(4), true, "Contains key"); + assert.deepEqual(table.containsKey(200), false, "Not contains key"); + var callback = function (k) + { + return k > 20; + }; + assert.deepEqual(table.containsKey(0, callback), true, "Contains key greater than 20"); + callback = function (k) + { + return k < 0; + }; + assert.deepEqual(table.containsKey(0, callback), false, "Not contains negative key"); +}); + +QUnit.test("HashTable - Clear test", function (assert) +{ + var table = new ds.HashTable(50); + for (var i = 0; i < 100; i++) + table.insert(i, i % 20); + assert.deepEqual(table.isEmpty(), false, "Before clear"); + table.clear(); + assert.deepEqual(table.isEmpty(), true, "After clear"); +}); + +QUnit.test("HashTable - Get number of keys test", function (assert) +{ + var table = new ds.HashTable(50); + assert.deepEqual(table.getNumberOfKeys(), 0, "Before insertion"); + for (var i = 0; i < 100; i++) + table.insert(i, i % 20); + assert.deepEqual(table.getNumberOfKeys(), 100, "After insertion"); +}); + +QUnit.test("HashTable - Is empty test", function (assert) +{ + var table = new ds.HashTable(50); + assert.deepEqual(table.isEmpty(), true, "Before insertion"); + for (var i = 0; i < 100; i++) + table.insert(i, i % 20); + assert.deepEqual(table.isEmpty(), false, "Before clear"); + table.clear(); + assert.deepEqual(table.isEmpty(), true, "After clear"); +}); diff --git a/Tests/LinkedList_Test.js b/Tests/LinkedList_Test.js deleted file mode 100644 index dfcd8fb..0000000 --- a/Tests/LinkedList_Test.js +++ /dev/null @@ -1,385 +0,0 @@ -/** - * Created by Stefano on 31/03/14. - */ - -test("LinkedList - Init test", function () { - var list = new LinkedList(0, 1, 2); - deepEqual(list.toArray(), [0, 1, 2], "Init list"); - list = new LinkedList(0); - deepEqual(list.toArray(), [0], "Init list"); -}); - -test("LinkedList - Init test with range", function () { - var list = new LinkedList(new Range(0, 5)); - deepEqual(list.toArray(), [0, 1, 2, 3, 4, 5], "Init list with range"); -}); - -test("LinkedList - Push test", function () { - var list = new LinkedList(); - list.pushFront(0); - list.pushFront(1); - list.pushBack(2); - list.pushBack(3); - deepEqual(list.getItem(0), 1, "Push front 1"); - deepEqual(list.getItem(1), 0, "Push front 0"); - deepEqual(list.getItem(2), 2, "Push back 2"); - deepEqual(list.getItem(3), 3, "Push back 3"); -}); - -test("LinkedList - Pop test", function () { - var list = new LinkedList(); - list.pushFront(0); - list.pushFront(1); - list.pushBack(2); - list.pushBack(3); - deepEqual(list.popBack(), 3, "Pop back 3"); - deepEqual(list.popFront(), 1, "Pop front 1"); - deepEqual(list.popBack(), 2, "Pop back 2"); - deepEqual(list.popFront(), 0, "Pop front 0"); -}); - -test("LinkedList - Remove at test", function () { - var list = new LinkedList(); - list.pushFront(0); - list.pushFront(1); - list.pushBack(2); - list.pushBack(3); - deepEqual(list.removeAt(1), 0, "Remove at 1"); - deepEqual(list.removeAt(1), 2, "Remove at 1"); - deepEqual(list.removeAt(1), 3, "Remove at 1"); - deepEqual(list.removeAt(0), 1, "Remove at 0"); -}); - -test("LinkedList - Remove test", function () { - var list = new LinkedList(); - for (var i = 0; i < 30; i++) - list.pushBack(i % 10); - list.pushBack(15); - var callback = function (item) { - return !(item % 2) && item > 5; - }; - list.remove(0); - deepEqual(list.indexOf(0), 9, "Remove 0"); - list.remove(15); - deepEqual(list.indexOf(15), -1, "Remove 15"); - list.remove(9); - list.remove(9); - list.remove(9); - deepEqual(list.indexOf(9), -1, "Remove 9"); - list.remove(0, callback); - deepEqual(list.indexOf(6), 13, "Remove the first even numbers greater than 5"); -}); - -test("LinkedList - Remove all test", function () { - var list = new LinkedList(); - for (var i = 0; i < 30; i++) - list.pushBack(i % 10); - var callback = function (item) { - return !(item % 2) && item > 5; - }; - list.removeAll(0); - deepEqual(list.indexOf(0), -1, "Remove all 0"); - list.removeAll(9); - deepEqual(list.indexOf(9), -1, "Remove all 9"); - list.removeAll(0, callback); - deepEqual(list.indexOf(8), -1, "Remove all the even numbers greater than 5"); -}); - -test("LinkedList - Remove segment test", function () { - var list = new LinkedList(); - for (var i = 0; i < 10; i++) - list.pushBack(i); - deepEqual(list.removeSegment(2, 6), [2, 3, 4, 5, 6], "Remove the segment from the list"); - deepEqual(list.toArray(), [0, 1, 7, 8, 9], "Remove the segment from the list"); - deepEqual(list.getLength(), 5, "Remove the segment from the list"); - deepEqual(list.removeSegment(2, 1), [7, 8, 9], "Remove the segment from the list"); - deepEqual(list.toArray(), [0, 1], "Remove the segment from the list"); - deepEqual(list.getLength(), 2, "Remove the segment from the list"); -}); - -test("LinkedList - Modify at test", function () { - var list = new LinkedList(); - for (var i = 0; i < 4; i++) - list.pushBack(i); - list.modifyAt(2, 6); - deepEqual(list.toArray(), [0, 1, 6, 3], "Change at valid position"); - list.modifyAt(5, 5); - deepEqual(list.toArray(), [0, 1, 6, 3], "Change at non valid position"); -}); - -test("LinkedList - To array test", function () { - var list = new LinkedList(); - list.pushFront(0); - list.pushFront(1); - list.pushBack(2); - list.pushBack(3); - var array = list.toArray(); - deepEqual(array[0], 1, "To array"); - deepEqual(array[1], 0, "To array"); - deepEqual(array[2], 2, "To array"); - deepEqual(array[3], 3, "To array"); -}); - -test("LinkedList - From array test", function () { - var array = [5, 2, 6, 4]; - var list = new LinkedList(); - list.fromArray(array); - deepEqual(list.getItem(0), 5, "From array"); - deepEqual(list.getItem(1), 2, "From array"); - deepEqual(list.getItem(2), 6, "From array"); - deepEqual(list.getItem(3), 4, "From array"); -}); - -test("LinkedList - Filter test", function () { - var list = new LinkedList(); - const length = 100; - - for (var i = 0; i < length; i++) - list.pushFront(i); - - var result = list.filter(function (item) { - return 1 - item % 2; - }); - - deepEqual(result[0], 98, "Filter of the even values"); - deepEqual(result[result.length - 1], 0, "Filter on the even values"); -}); - -test("LinkedList - Iterator test", function () { - var list = new LinkedList(); - - for (var i = 0; i < 100; i++) - list.pushBack(i); - - var it = list.getIterator(); - - var j = 0; - for (it.first(); !it.isDone(); it.next(), j++) { - deepEqual(it.getItem(), j, "Check iterator position"); - } - -}); - -test("LinkedList - Add at test", function () { - var list = new LinkedList(); - list.addAt(5, 0); - deepEqual(list.peek(), 5, "Add at 0"); - list.addAt(2, 1); - deepEqual(list.getItem(1), 2, "Add at 1"); - list.addAt(15, 6); - deepEqual(list.getItem(2), undefined, "Add at 6"); - deepEqual(list.getItem(5), undefined, "Add at 6"); - deepEqual(list.getItem(6), 15, "Add at 6"); - list.addAt(30, 6); - deepEqual(list.getItem(6), 30, "Add at 6"); - deepEqual(list.getItem(7), 15, "Add at 6"); - list.addAt(6, 0); - deepEqual(list.peek(), 6, "Add at 0"); -}); - -test("LinkedList - MultiPop test", function () { - var list = new LinkedList(); - list.pushFront(0); - list.pushFront(1); - list.pushBack(2); - list.pushBack(3); - deepEqual(list.multiPopBack(2), [3, 2], "Multi pop back"); - deepEqual(list.multiPopFront(2), [1, 0], "Multi pop front"); -}); - -test("LinkedList - Get length test", function () { - var list = new LinkedList(); - deepEqual(list.getLength(), 0, "Get length empty"); - list.pushFront(0); - list.pushFront(1); - list.pushBack(2); - list.pushBack(3); - deepEqual(list.getLength(), 4, "Get length"); - list.multiPopBack(2); - deepEqual(list.getLength(), 2, "Get length"); - -}); - -test("LinkedList - Peek test", function () { - var list = new LinkedList(); - list.pushFront(0); - deepEqual(list.peek(), 0, "Peek"); - list.pushFront(1); - list.pushBack(2); - deepEqual(list.peek(), 1, "Peek"); - list.pushBack(3); - deepEqual(list.peek(), 1, "Peek"); -}); - -test("LinkedList - Clear test", function () { - var list = new LinkedList(); - list.pushFront(0); - list.pushFront(1); - list.pushBack(2); - list.pushBack(3); - list.clear(); - deepEqual(list.getLength(), 0, "Clear the list"); - -}); - -test("LinkedList - Is empty test", function () { - var list = new LinkedList(); - deepEqual(list.isEmpty(), true, "Is empty"); - list.pushFront(0); - list.pushFront(1); - list.pushBack(2); - list.pushBack(3); - deepEqual(list.isEmpty(), false, "Is not empty"); - list.clear(); - deepEqual(list.isEmpty(), true, "Is empty"); -}); - -test("LinkedList - Contains test", function () { - var list = new LinkedList(); - list.pushBack(0); - list.pushBack(2); - deepEqual(list.contains(0), true, "Contains 0"); - deepEqual(list.contains(2), true, "Contains 2"); - deepEqual(list.contains(1), false, "Not contains 1"); - var callback = function (item) { - return item > 0; - }; - deepEqual(list.contains(null, callback), true, "Contains a value > 0"); - callback = function (item) { - return item < 0; - }; - deepEqual(list.contains(null, callback), false, "Contains a value < 0"); -}); - -test("LinkedList - Execute test", function () { - var list = new LinkedList(); - list.pushBack(0); - list.pushBack(2); - var callback = function (item) { - return item * 2; - }; - list.execute(callback); - deepEqual(list.getItem(0), 0, "Execute for item 0"); - deepEqual(list.getItem(1), 4, "Execute for item 1"); -}); - -test("LinkedList - Index of test", function () { - var list = new LinkedList(); - for (var i = 0; i < 10; i++) - list.pushBack(i); - var callback = function (item) { - return !(item % 2) && item > 5; - }; - deepEqual(list.indexOf(0), 0, "Index of 0"); - deepEqual(list.indexOf(15), -1, "Index of 15"); - deepEqual(list.indexOf(5), 5, "Index of 5"); - list.removeAt(5); - deepEqual(list.indexOf(6), 5, "Index of 6"); - deepEqual(list.indexOf(null, callback), 5, "Index of the first even number greater than 5"); -}); - -test("LinkedList - Last index of test", function () { - var list = new LinkedList(); - for (var i = 0; i < 10; i++) - list.pushBack(i); - var callback = function (item) { - return !(item % 2) && item > 5; - }; - deepEqual(list.lastIndexOf(0), 0, "Last index of 0"); - deepEqual(list.lastIndexOf(15), -1, "Last index of 15"); - deepEqual(list.lastIndexOf(5), 5, "Last index of 5"); - list.removeAt(5); - deepEqual(list.lastIndexOf(6), 5, "Last index of 6"); - deepEqual(list.lastIndexOf(null, callback), 7, "Index of the last even number greater than 5"); -}); - -test("LinkedList - Indexes of test", function () { - var list = new LinkedList(); - for (var i = 0; i < 30; i++) - list.pushBack(i % 10); - var callback = function (item) { - return !(item % 2) && item > 5; - }; - deepEqual(list.allIndexesOf(0), [0, 10, 20], "Indexes of 0"); - deepEqual(list.allIndexesOf(15), [], "Indexes of 15"); - deepEqual(list.allIndexesOf(5), [5, 15, 25], "Indexes of 5"); - list.removeAt(5); - deepEqual(list.allIndexesOf(5), [14, 24], "Indexes of 5"); - deepEqual(list.allIndexesOf(6), [5, 15, 25], "Indexes of 6"); - deepEqual(list.allIndexesOf(null, callback), [5, 7, 15, 17, 25, 27], "Indexes of the even numbers greater than 5"); -}); - -test("LinkedList - Join test", function () { - var listA = new LinkedList(); - var listB = new LinkedList(); - for (var i = 0; i < 5; i++) { - listA.pushBack(i); - listB.pushBack(i); - } - listA.join(listB); - deepEqual(listA.allIndexesOf(3), [3, 8], "Join of the lists"); - deepEqual(listA.getLength(), 10, "Check the length of the list"); -}); - -test("LinkedList - Divide test", function () { - var list = new LinkedList(); - for (var i = 0; i < 10; i++) - list.pushBack(i); - var listA = list.divide(-1); - deepEqual(listA.isEmpty(), true, "Divide before start"); - var listB = list.divide(10); - deepEqual(listB.isEmpty(), true, "Divide after end"); - var listC = list.divide(8); - deepEqual(listC.getItem(0), 8, "Divide at valid position"); - deepEqual(listC.getItem(1), 9, "Divide at valid position"); - deepEqual(listC.getLength(), 2, "Divide at valid position"); - deepEqual(list.getItem(8), undefined, "Divide at valid position"); - deepEqual(list.getLength(), 8, "Divide at valid position"); - var listD = list.divide(0); - deepEqual(listD.getLength(), 8, "Divide at the first position"); - deepEqual(listD.getItem(0), 0, "Divide at the first position"); - deepEqual(listD.getItem(8), undefined, "Divide at the first position"); - deepEqual(listD.getItem(7), 7, "Divide at the first position"); - deepEqual(list.getLength(), 0, "Divide at the first position"); - deepEqual(list.getItem(0), undefined, "Divide at the first position"); -}); - -test("LinkedList - Clone test", function () { - var list = new LinkedList(); - for (var i = 0; i < 10; i++) - list.pushBack(i); - var clone = list.clone(); - var it = clone.getIterator(); - var j = 0; - for (it.first(); !it.isDone(); it.next(), j++) - deepEqual(it.getItem(), j, "Clone of the list"); -}); - -test("LinkedList - Clone distinct test", function () { - var list = new LinkedList(); - for (var i = 0; i < 20; i++) - list.pushBack(i % 10); - var clone = list.cloneDistinct(); - deepEqual(clone.allIndexesOf(2), [2], "Clone of the list"); -}); - -test("LinkedList - Split test", function () { - var list = new LinkedList(); - for (var i = 0; i < 7; i++) - list.pushBack(i); - var lists = list.split(3); - deepEqual(lists.length, 3, "Check the number of lists created"); - deepEqual(lists[0].toArray(), [0, 1, 2], "Check the items in the lists created"); - deepEqual(lists[1].toArray(), [3, 4, 5], "Check the items in the lists created"); - deepEqual(lists[2].toArray(), [6], "Check the items in the lists created"); -}); - -test("LinkedList - Count test", function () { - var list = new LinkedList(); - for (var i = 0; i < 10; i++) - list.pushBack(i); - var callback = function (item) { - return item > 4; - }; - deepEqual(list.count(callback), 5, "Count the items that are greater than 4"); -}); \ No newline at end of file diff --git a/Tests/LinkedList_Test.ts b/Tests/LinkedList_Test.ts new file mode 100644 index 0000000..d04bf42 --- /dev/null +++ b/Tests/LinkedList_Test.ts @@ -0,0 +1,427 @@ +/** + * Created by Stefano on 31/03/14. + */ + +QUnit.test("LinkedList - Init test", function (assert) +{ + var list = new ds.LinkedList(0, 1, 2); + assert.deepEqual(list.toArray(), [0, 1, 2], "Init list"); + list = new ds.LinkedList(0); + assert.deepEqual(list.toArray(), [0], "Init list"); +}); + +QUnit.test("LinkedList - Init test with range", function (assert) +{ + var list = new ds.LinkedList(ds.Range(0, 5)); + assert.deepEqual(list.toArray(), [0, 1, 2, 3, 4, 5], "Init list with range"); +}); + +QUnit.test("LinkedList - Push test", function (assert) +{ + var list = new ds.LinkedList(); + list.pushFront(0); + list.pushFront(1); + list.pushBack(2); + list.pushBack(3); + assert.deepEqual(list.getItem(0), 1, "Push front 1"); + assert.deepEqual(list.getItem(1), 0, "Push front 0"); + assert.deepEqual(list.getItem(2), 2, "Push back 2"); + assert.deepEqual(list.getItem(3), 3, "Push back 3"); +}); + +QUnit.test("LinkedList - Pop test", function (assert) +{ + var list = new ds.LinkedList(); + list.pushFront(0); + list.pushFront(1); + list.pushBack(2); + list.pushBack(3); + assert.deepEqual(list.popBack(), 3, "Pop back 3"); + assert.deepEqual(list.popFront(), 1, "Pop front 1"); + assert.deepEqual(list.popBack(), 2, "Pop back 2"); + assert.deepEqual(list.popFront(), 0, "Pop front 0"); +}); + +QUnit.test("LinkedList - Remove at test", function (assert) +{ + var list = new ds.LinkedList(); + list.pushFront(0); + list.pushFront(1); + list.pushBack(2); + list.pushBack(3); + assert.deepEqual(list.removeAt(1), 0, "Remove at 1"); + assert.deepEqual(list.removeAt(1), 2, "Remove at 1"); + assert.deepEqual(list.removeAt(1), 3, "Remove at 1"); + assert.deepEqual(list.removeAt(0), 1, "Remove at 0"); +}); + +QUnit.test("LinkedList - Remove test", function (assert) +{ + var list = new ds.LinkedList(); + for (var i = 0; i < 30; i++) + list.pushBack(i % 10); + list.pushBack(15); + var callback = function (item) + { + return !(item % 2) && item > 5; + }; + list.remove(0); + assert.deepEqual(list.indexOf(0), 9, "Remove 0"); + list.remove(15); + assert.deepEqual(list.indexOf(15), -1, "Remove 15"); + list.remove(9); + list.remove(9); + list.remove(9); + assert.deepEqual(list.indexOf(9), -1, "Remove 9"); + list.remove(0, callback); + assert.deepEqual(list.indexOf(6), 13, "Remove the first even numbers greater than 5"); +}); + +QUnit.test("LinkedList - Remove all test", function (assert) +{ + var list = new ds.LinkedList(); + for (var i = 0; i < 30; i++) + list.pushBack(i % 10); + var callback = function (item) + { + return !(item % 2) && item > 5; + }; + list.removeAll(0); + assert.deepEqual(list.indexOf(0), -1, "Remove all 0"); + list.removeAll(9); + assert.deepEqual(list.indexOf(9), -1, "Remove all 9"); + list.removeAll(0, callback); + assert.deepEqual(list.indexOf(8), -1, "Remove all the even numbers greater than 5"); +}); + +QUnit.test("LinkedList - Remove segment test", function (assert) +{ + var list = new ds.LinkedList(); + for (var i = 0; i < 10; i++) + list.pushBack(i); + assert.deepEqual(list.removeSegment(2, 6), [2, 3, 4, 5, 6], "Remove the segment from the list"); + assert.deepEqual(list.toArray(), [0, 1, 7, 8, 9], "Remove the segment from the list"); + assert.deepEqual(list.getLength(), 5, "Remove the segment from the list"); + assert.deepEqual(list.removeSegment(2, 1), [7, 8, 9], "Remove the segment from the list"); + assert.deepEqual(list.toArray(), [0, 1], "Remove the segment from the list"); + assert.deepEqual(list.getLength(), 2, "Remove the segment from the list"); +}); + +QUnit.test("LinkedList - Modify at test", function (assert) +{ + var list = new ds.LinkedList(); + for (var i = 0; i < 4; i++) + list.pushBack(i); + list.modifyAt(2, 6); + assert.deepEqual(list.toArray(), [0, 1, 6, 3], "Change at valid position"); + list.modifyAt(5, 5); + assert.deepEqual(list.toArray(), [0, 1, 6, 3], "Change at non valid position"); +}); + +QUnit.test("LinkedList - To array test", function (assert) +{ + var list = new ds.LinkedList(); + list.pushFront(0); + list.pushFront(1); + list.pushBack(2); + list.pushBack(3); + var array = list.toArray(); + assert.deepEqual(array[0], 1, "To array"); + assert.deepEqual(array[1], 0, "To array"); + assert.deepEqual(array[2], 2, "To array"); + assert.deepEqual(array[3], 3, "To array"); +}); + +QUnit.test("LinkedList - From array test", function (assert) +{ + var array = [5, 2, 6, 4]; + var list = new ds.LinkedList(); + list.fromArray(array); + assert.deepEqual(list.getItem(0), 5, "From array"); + assert.deepEqual(list.getItem(1), 2, "From array"); + assert.deepEqual(list.getItem(2), 6, "From array"); + assert.deepEqual(list.getItem(3), 4, "From array"); +}); + +QUnit.test("LinkedList - Filter test", function (assert) +{ + var list = new ds.LinkedList(); + const length = 100; + + for (var i = 0; i < length; i++) + list.pushFront(i); + + var result = list.filter(function (item) + { + return Boolean(1 - item % 2); + }); + + assert.deepEqual(result[0], 98, "Filter of the even values"); + assert.deepEqual(result[result.length - 1], 0, "Filter on the even values"); +}); + +QUnit.test("LinkedList - Iterator test", function (assert) +{ + var list = new ds.LinkedList(); + + for (var i = 0; i < 100; i++) + list.pushBack(i); + + var it = list.getIterator(); + + var j = 0; + for (it.first(); !it.isDone(); it.next(), j++) + { + assert.deepEqual(it.getItem(), j, "Check iterator position"); + } + +}); + +QUnit.test("LinkedList - Add at test", function (assert) +{ + var list = new ds.LinkedList(); + list.addAt(5, 0); + assert.deepEqual(list.peek(), 5, "Add at 0"); + list.addAt(2, 1); + assert.deepEqual(list.getItem(1), 2, "Add at 1"); + list.addAt(15, 6); + assert.deepEqual(list.getItem(2), undefined, "Add at 6"); + assert.deepEqual(list.getItem(5), undefined, "Add at 6"); + assert.deepEqual(list.getItem(6), 15, "Add at 6"); + list.addAt(30, 6); + assert.deepEqual(list.getItem(6), 30, "Add at 6"); + assert.deepEqual(list.getItem(7), 15, "Add at 6"); + list.addAt(6, 0); + assert.deepEqual(list.peek(), 6, "Add at 0"); +}); + +QUnit.test("LinkedList - MultiPop test", function (assert) +{ + var list = new ds.LinkedList(); + list.pushFront(0); + list.pushFront(1); + list.pushBack(2); + list.pushBack(3); + assert.deepEqual(list.multiPopBack(2), [3, 2], "Multi pop back"); + assert.deepEqual(list.multiPopFront(2), [1, 0], "Multi pop front"); +}); + +QUnit.test("LinkedList - Get length test", function (assert) +{ + var list = new ds.LinkedList(); + assert.deepEqual(list.getLength(), 0, "Get length empty"); + list.pushFront(0); + list.pushFront(1); + list.pushBack(2); + list.pushBack(3); + assert.deepEqual(list.getLength(), 4, "Get length"); + list.multiPopBack(2); + assert.deepEqual(list.getLength(), 2, "Get length"); + +}); + +QUnit.test("LinkedList - Peek test", function (assert) +{ + var list = new ds.LinkedList(); + list.pushFront(0); + assert.deepEqual(list.peek(), 0, "Peek"); + list.pushFront(1); + list.pushBack(2); + assert.deepEqual(list.peek(), 1, "Peek"); + list.pushBack(3); + assert.deepEqual(list.peek(), 1, "Peek"); +}); + +QUnit.test("LinkedList - Clear test", function (assert) +{ + var list = new ds.LinkedList(); + list.pushFront(0); + list.pushFront(1); + list.pushBack(2); + list.pushBack(3); + list.clear(); + assert.deepEqual(list.getLength(), 0, "Clear the list"); + +}); + +QUnit.test("LinkedList - Is empty test", function (assert) +{ + var list = new ds.LinkedList(); + assert.deepEqual(list.isEmpty(), true, "Is empty"); + list.pushFront(0); + list.pushFront(1); + list.pushBack(2); + list.pushBack(3); + assert.deepEqual(list.isEmpty(), false, "Is not empty"); + list.clear(); + assert.deepEqual(list.isEmpty(), true, "Is empty"); +}); + +QUnit.test("LinkedList - Contains test", function (assert) +{ + var list = new ds.LinkedList(); + list.pushBack(0); + list.pushBack(2); + assert.deepEqual(list.contains(0), true, "Contains 0"); + assert.deepEqual(list.contains(2), true, "Contains 2"); + assert.deepEqual(list.contains(1), false, "Not contains 1"); + var callback = function (item) + { + return item > 0; + }; + assert.deepEqual(list.contains(null, callback), true, "Contains a value > 0"); + callback = function (item) + { + return item < 0; + }; + assert.deepEqual(list.contains(null, callback), false, "Contains a value < 0"); +}); + +QUnit.test("LinkedList - Execute test", function (assert) +{ + var list = new ds.LinkedList(); + list.pushBack(0); + list.pushBack(2); + var callback = function (item) + { + return item * 2; + }; + list.execute(callback); + assert.deepEqual(list.getItem(0), 0, "Execute for item 0"); + assert.deepEqual(list.getItem(1), 4, "Execute for item 1"); +}); + +QUnit.test("LinkedList - Index of test", function (assert) +{ + var list = new ds.LinkedList(); + for (var i = 0; i < 10; i++) + list.pushBack(i); + var callback = function (item) + { + return !(item % 2) && item > 5; + }; + assert.deepEqual(list.indexOf(0), 0, "Index of 0"); + assert.deepEqual(list.indexOf(15), -1, "Index of 15"); + assert.deepEqual(list.indexOf(5), 5, "Index of 5"); + list.removeAt(5); + assert.deepEqual(list.indexOf(6), 5, "Index of 6"); + assert.deepEqual(list.indexOf(null, callback), 5, "Index of the first even number greater than 5"); +}); + +QUnit.test("LinkedList - Last index of test", function (assert) +{ + var list = new ds.LinkedList(); + for (var i = 0; i < 10; i++) + list.pushBack(i); + var callback = function (item) + { + return !(item % 2) && item > 5; + }; + assert.deepEqual(list.lastIndexOf(0), 0, "Last index of 0"); + assert.deepEqual(list.lastIndexOf(15), -1, "Last index of 15"); + assert.deepEqual(list.lastIndexOf(5), 5, "Last index of 5"); + list.removeAt(5); + assert.deepEqual(list.lastIndexOf(6), 5, "Last index of 6"); + assert.deepEqual(list.lastIndexOf(null, callback), 7, "Index of the last even number greater than 5"); +}); + +QUnit.test("LinkedList - Indexes of test", function (assert) +{ + var list = new ds.LinkedList(); + for (var i = 0; i < 30; i++) + list.pushBack(i % 10); + var callback = function (item) + { + return !(item % 2) && item > 5; + }; + assert.deepEqual(list.allIndexesOf(0), [0, 10, 20], "Indexes of 0"); + assert.deepEqual(list.allIndexesOf(15), [], "Indexes of 15"); + assert.deepEqual(list.allIndexesOf(5), [5, 15, 25], "Indexes of 5"); + list.removeAt(5); + assert.deepEqual(list.allIndexesOf(5), [14, 24], "Indexes of 5"); + assert.deepEqual(list.allIndexesOf(6), [5, 15, 25], "Indexes of 6"); + assert.deepEqual(list.allIndexesOf(null, callback), [5, 7, 15, 17, 25, 27], "Indexes of the even numbers greater than 5"); +}); + +QUnit.test("LinkedList - Join test", function (assert) +{ + var listA = new ds.LinkedList(); + var listB = new ds.LinkedList(); + for (var i = 0; i < 5; i++) + { + listA.pushBack(i); + listB.pushBack(i); + } + listA.join(listB); + assert.deepEqual(listA.allIndexesOf(3), [3, 8], "Join of the lists"); + assert.deepEqual(listA.getLength(), 10, "Check the length of the list"); +}); + +QUnit.test("LinkedList - Divide test", function (assert) +{ + var list = new ds.LinkedList(); + for (var i = 0; i < 10; i++) + list.pushBack(i); + var listA = list.divide(-1); + assert.deepEqual(listA.isEmpty(), true, "Divide before start"); + var listB = list.divide(10); + assert.deepEqual(listB.isEmpty(), true, "Divide after end"); + var listC = list.divide(8); + assert.deepEqual(listC.getItem(0), 8, "Divide at valid position"); + assert.deepEqual(listC.getItem(1), 9, "Divide at valid position"); + assert.deepEqual(listC.getLength(), 2, "Divide at valid position"); + assert.deepEqual(list.getItem(8), undefined, "Divide at valid position"); + assert.deepEqual(list.getLength(), 8, "Divide at valid position"); + var listD = list.divide(0); + assert.deepEqual(listD.getLength(), 8, "Divide at the first position"); + assert.deepEqual(listD.getItem(0), 0, "Divide at the first position"); + assert.deepEqual(listD.getItem(8), undefined, "Divide at the first position"); + assert.deepEqual(listD.getItem(7), 7, "Divide at the first position"); + assert.deepEqual(list.getLength(), 0, "Divide at the first position"); + assert.deepEqual(list.getItem(0), undefined, "Divide at the first position"); +}); + +QUnit.test("LinkedList - Clone test", function (assert) +{ + var list = new ds.LinkedList(); + for (var i = 0; i < 10; i++) + list.pushBack(i); + var clone = list.clone(); + var it = clone.getIterator(); + var j = 0; + for (it.first(); !it.isDone(); it.next(), j++) + assert.deepEqual(it.getItem(), j, "Clone of the list"); +}); + +QUnit.test("LinkedList - Clone distinct test", function (assert) +{ + var list = new ds.LinkedList(); + for (var i = 0; i < 20; i++) + list.pushBack(i % 10); + var clone = list.cloneDistinct(); + assert.deepEqual(clone.allIndexesOf(2), [2], "Clone of the list"); +}); + +QUnit.test("LinkedList - Split test", function (assert) +{ + var list = new ds.LinkedList(); + for (var i = 0; i < 7; i++) + list.pushBack(i); + var lists = list.split(3); + assert.deepEqual(lists.length, 3, "Check the number of lists created"); + assert.deepEqual(lists[0].toArray(), [0, 1, 2], "Check the items in the lists created"); + assert.deepEqual(lists[1].toArray(), [3, 4, 5], "Check the items in the lists created"); + assert.deepEqual(lists[2].toArray(), [6], "Check the items in the lists created"); +}); + +QUnit.test("LinkedList - Count test", function (assert) +{ + var list = new ds.LinkedList(); + for (var i = 0; i < 10; i++) + list.pushBack(i); + var callback = function (item) + { + return item > 4; + }; + assert.deepEqual(list.count(callback), 5, "Count the items that are greater than 4"); +}); \ No newline at end of file diff --git a/Tests/PriorityQueue_Test.js b/Tests/PriorityQueue_Test.js deleted file mode 100644 index 09c2b86..0000000 --- a/Tests/PriorityQueue_Test.js +++ /dev/null @@ -1,197 +0,0 @@ -/** - * Created by Battistella Stefano on 31/03/14. - */ - -test("PriorityQueue - Enqueue test", function () { - var queue = new PriorityQueue(); - queue.enqueue(5, 0); - deepEqual(queue.peek(), 0, "Enqueue 0"); - queue.enqueue(2, 6); - deepEqual(queue.getItem(0), 0, "Enqueue 6"); - deepEqual(queue.getItem(1), 6, "Enqueue 6"); -}); - -test("PriorityQueue - MultiEnqueue test", function () { - var queue = new PriorityQueue(); - queue.multiEnqueue(3, [0, 2]); - deepEqual(queue.multiDequeue(2), [0, 2], "MultiEnqueue 2 items"); - queue.multiEnqueue(4, [2]); - queue.multiEnqueue(5, [4, 5, 8]); - deepEqual(queue.multiDequeue(4), [4, 5, 8, 2], "MultiDequeue 4 items"); - queue.multiEnqueue(0, []); - deepEqual(queue.multiDequeue(1), [], "MultiEnqueue 0 items"); -}); - -test("PriorityQueue - Dequeue test", function () { - var queue = new PriorityQueue(); - queue.enqueue(5, 0); - queue.enqueue(2, 2); - deepEqual(queue.dequeue(), 0, "Dequeue"); - deepEqual(queue.dequeue(), 2, "Dequeue"); - deepEqual(queue.dequeue(), undefined, "Check length if too much dequeue"); -}); - -test("PriorityQueue - MultiDequeue test", function () { - var queue = new PriorityQueue(); - queue.enqueue(10, 0); - queue.enqueue(8, 2); - deepEqual(queue.multiDequeue(1), [0], "MultiDequeue 1 time"); - deepEqual(queue.getLength(), 1, "MultiDequeue 1 time check length"); - queue.enqueue(9, 4); - queue.enqueue(4, 5); - queue.enqueue(6, 8); - deepEqual(queue.multiDequeue(7), [4, 2, 8, 5], "MultiDequeue 7 times"); - deepEqual(queue.getLength(), 0, "MultiDequeue 7 time check length"); - deepEqual(queue.multiDequeue(1), [], "MultiDequeue 1 time with queue empty"); -}); - -test("PriorityQueue - Remove test", function () { - var queue = new PriorityQueue(); - queue.enqueue(4, 0); - queue.enqueue(3, 2); - queue.enqueue(2, 4); - queue.enqueue(1, 5); - queue.enqueue(0, 8); - queue.remove(2, 2); - deepEqual(queue.multiDequeue(3), [0, 2, 8], "Remove from position 2 for 2"); -}); - -test("PriorityQueue - Is empty test", function () { - var queue = new PriorityQueue(); - queue.enqueue(5, 0); - queue.enqueue(2, 2); - deepEqual(queue.isEmpty(), false, "Is empty"); - queue.clear(); - deepEqual(queue.isEmpty(), true, "Is empty"); -}); - -test("PriorityQueue - Clear test", function () { - var queue = new PriorityQueue(); - queue.enqueue(5, 0); - queue.enqueue(5, 2); - queue.clear(); - deepEqual(queue.isEmpty(), true, "Clear queue"); -}); - -test("PriorityQueue - Iterator test", function () { - var queue = new PriorityQueue(); - for (var i = 0; i < 10; i++) - queue.enqueue(10 - Math.floor(i / 2), i); - var j = 0; - var it = queue.getIterator(); - for (it.first(); !it.isDone(); it.next(), j++) - deepEqual(it.getItem(), j, "Get next item " + j); - j--; - for (it.last(); !it.isDone(); it.previous(), j--) - deepEqual(it.getItem(), j, "Get previous item " + j); -}); - -test("PriorityQueue - Contains priority test", function () { - var queue = new PriorityQueue(); - queue.enqueue(5, 0); - queue.enqueue(2, 2); - deepEqual(queue.containsPriority(5), true, "Contains priority 5"); - deepEqual(queue.containsPriority(2), true, "Contains priority 2"); - deepEqual(queue.containsPriority(1), false, "Not contains priority 1"); - var callback = function (item) { - return item > 3; - }; - deepEqual(queue.containsPriority(null, callback), true, "Contains a priority > 3"); - callback = function (item) { - return item < 2; - }; - deepEqual(queue.containsPriority(null, callback), false, "Contains a priority < 2"); -}); - -test("PriorityQueue - Get items test", function () { - var queue = new PriorityQueue(); - queue.enqueue(5, 0); - queue.enqueue(5, 2); - queue.enqueue(5, 5); - deepEqual(queue.getItems(5), [0, 2, 5], "Get items with priority 5"); - deepEqual(queue.getItems(1), [], "Get items with priority 1"); -}); - -test("PriorityQueue - To queue test", function () { - var priorityQueue = new PriorityQueue(); - priorityQueue.enqueue(5, 0); - priorityQueue.enqueue(5, 2); - priorityQueue.enqueue(5, 5); - var queue = priorityQueue.toQueue(); - deepEqual(queue.items, [0, 2, 5], "Check the to queue method"); -}); - -test("PriorityQueue - Execute test", function () { - var queue = new PriorityQueue(); - queue.enqueue(4, 0); - queue.enqueue(3, 2); - var callback = function (item) { - return item * 2; - }; - queue.execute(callback); - deepEqual(queue.getItem(0), 0, "Execute for item 0"); - deepEqual(queue.getItem(1), 4, "Execute for item 1"); -}); - -test("PriorityQueue - Remove test", function () { - var queue = new PriorityQueue(); - queue.enqueue(4, 0); - queue.enqueue(3, 1); - queue.enqueue(2, 2); - queue.enqueue(1, 3); - queue.enqueue(0, 4); - for (var i = 0; i < 5; i++) - deepEqual(queue.getItem(i), i, "Check queue correctness"); - queue.changePriority(3, 8); - for (var j = 0; j < 5; j++) { - if (!j) - deepEqual(queue.getItem(j), 3, "Check increase priority"); - else if (j < 4) - deepEqual(queue.getItem(j), j - 1, "Check increase priority"); - else - deepEqual(queue.getItem(j), j, "Check increase priority"); - } - queue.changePriority(3, -4); - for (var k = 0; k < 5; k++) { - if (!k) - deepEqual(queue.getItem(k), 3, "Check decrease priority"); - else if (k < 3) - deepEqual(queue.getItem(k), k - 1, "Check decrease priority"); - else if (k === 3) - deepEqual(queue.getItem(k), 4, "Check decrease priority"); - else - deepEqual(queue.getItem(k), 2, "Check decrease priority"); - } - -}); - -test("PriorityQueue - Filter test", function () { - var queue = new PriorityQueue(); - const length = 100; - - for (var i = 0; i < length; i++) - queue.enqueue(i, i); - - var result = queue.filter(function (item) { - return 1 - item % 2; - }); - - deepEqual(result[0], 98, "Filter of the even values"); - deepEqual(result[result.length - 1], 0, "Filter on the even values"); -}); - -test("PriorityQueue - Clone test", function () { - var queue = new PriorityQueue(); - for (var i = 0; i < 10; i++) - queue.enqueue(i, i); - var clone = queue.clone(); - deepEqual(clone.multiDequeue(10), [9, 8, 7, 6, 5, 4, 3, 2, 1, 0], "Clone of the queue"); -}); - -test("PriorityQueue - Clone distinct test", function () { - var queue = new PriorityQueue(); - for (var i = 0; i < 40; i++) - queue.enqueue(i % 20, i % 10); - var clone = queue.cloneDistinct(); - deepEqual(clone.multiDequeue(10), [9, 8, 7, 6, 5, 4, 3, 2, 1, 0], "Clone of the queue"); -}); \ No newline at end of file diff --git a/Tests/PriorityQueue_Test.ts b/Tests/PriorityQueue_Test.ts new file mode 100644 index 0000000..a41d44a --- /dev/null +++ b/Tests/PriorityQueue_Test.ts @@ -0,0 +1,219 @@ +/** + * Created by Battistella Stefano on 31/03/14. + */ + +QUnit.test("PriorityQueue - Enqueue test", function (assert) +{ + var queue = new ds.PriorityQueue(); + queue.enqueue(5, 0); + assert.deepEqual(queue.peek(), 0, "Enqueue 0"); + queue.enqueue(2, 6); + assert.deepEqual(queue.getItem(0), 0, "Enqueue 6"); + assert.deepEqual(queue.getItem(1), 6, "Enqueue 6"); +}); + +QUnit.test("PriorityQueue - MultiEnqueue test", function (assert) +{ + var queue = new ds.PriorityQueue(); + queue.multiEnqueue(3, [0, 2]); + assert.deepEqual(queue.multiDequeue(2), [0, 2], "MultiEnqueue 2 items"); + queue.multiEnqueue(4, [2]); + queue.multiEnqueue(5, [4, 5, 8]); + assert.deepEqual(queue.multiDequeue(4), [4, 5, 8, 2], "MultiDequeue 4 items"); + queue.multiEnqueue(0, []); + assert.deepEqual(queue.multiDequeue(1), [], "MultiEnqueue 0 items"); +}); + +QUnit.test("PriorityQueue - Dequeue test", function (assert) +{ + var queue = new ds.PriorityQueue(); + queue.enqueue(5, 0); + queue.enqueue(2, 2); + assert.deepEqual(queue.dequeue(), 0, "Dequeue"); + assert.deepEqual(queue.dequeue(), 2, "Dequeue"); + assert.deepEqual(queue.dequeue(), undefined, "Check length if too much dequeue"); +}); + +QUnit.test("PriorityQueue - MultiDequeue test", function (assert) +{ + var queue = new ds.PriorityQueue(); + queue.enqueue(10, 0); + queue.enqueue(8, 2); + assert.deepEqual(queue.multiDequeue(1), [0], "MultiDequeue 1 time"); + assert.deepEqual(queue.getLength(), 1, "MultiDequeue 1 time check length"); + queue.enqueue(9, 4); + queue.enqueue(4, 5); + queue.enqueue(6, 8); + assert.deepEqual(queue.multiDequeue(7), [4, 2, 8, 5], "MultiDequeue 7 times"); + assert.deepEqual(queue.getLength(), 0, "MultiDequeue 7 time check length"); + assert.deepEqual(queue.multiDequeue(1), [], "MultiDequeue 1 time with queue empty"); +}); + +QUnit.test("PriorityQueue - Remove test", function (assert) +{ + var queue = new ds.PriorityQueue(); + queue.enqueue(4, 0); + queue.enqueue(3, 2); + queue.enqueue(2, 4); + queue.enqueue(1, 5); + queue.enqueue(0, 8); + queue.remove(2, 2); + assert.deepEqual(queue.multiDequeue(3), [0, 2, 8], "Remove from position 2 for 2"); +}); + +QUnit.test("PriorityQueue - Is empty test", function (assert) +{ + var queue = new ds.PriorityQueue(); + queue.enqueue(5, 0); + queue.enqueue(2, 2); + assert.deepEqual(queue.isEmpty(), false, "Is empty"); + queue.clear(); + assert.deepEqual(queue.isEmpty(), true, "Is empty"); +}); + +QUnit.test("PriorityQueue - Clear test", function (assert) +{ + var queue = new ds.PriorityQueue(); + queue.enqueue(5, 0); + queue.enqueue(5, 2); + queue.clear(); + assert.deepEqual(queue.isEmpty(), true, "Clear queue"); +}); + +QUnit.test("PriorityQueue - Iterator test", function (assert) +{ + var queue = new ds.PriorityQueue(); + for (var i = 0; i < 10; i++) + queue.enqueue(10 - Math.floor(i / 2), i); + var j = 0; + var it = queue.getIterator(); + for (it.first(); !it.isDone(); it.next(), j++) + assert.deepEqual(it.getItem(), j, "Get next item " + j); + j--; + for (it.last(); !it.isDone(); it.previous(), j--) + assert.deepEqual(it.getItem(), j, "Get previous item " + j); +}); + +QUnit.test("PriorityQueue - Contains priority test", function (assert) +{ + var queue = new ds.PriorityQueue(); + queue.enqueue(5, 0); + queue.enqueue(2, 2); + assert.deepEqual(queue.containsPriority(5), true, "Contains priority 5"); + assert.deepEqual(queue.containsPriority(2), true, "Contains priority 2"); + assert.deepEqual(queue.containsPriority(1), false, "Not contains priority 1"); + var callback = function (item) + { + return item > 3; + }; + assert.deepEqual(queue.containsPriority(null, callback), true, "Contains a priority > 3"); + callback = function (item) + { + return item < 2; + }; + assert.deepEqual(queue.containsPriority(null, callback), false, "Contains a priority < 2"); +}); + +QUnit.test("PriorityQueue - Get items test", function (assert) +{ + var queue = new ds.PriorityQueue(); + queue.enqueue(5, 0); + queue.enqueue(5, 2); + queue.enqueue(5, 5); + assert.deepEqual(queue.getItems(5), [0, 2, 5], "Get items with priority 5"); + assert.deepEqual(queue.getItems(1), [], "Get items with priority 1"); +}); + +QUnit.test("PriorityQueue - To queue test", function (assert) +{ + var priorityQueue = new ds.PriorityQueue(); + priorityQueue.enqueue(5, 0); + priorityQueue.enqueue(5, 2); + priorityQueue.enqueue(5, 5); + var queue = priorityQueue.toQueue(); + assert.deepEqual(queue.items, [0, 2, 5], "Check the to queue method"); +}); + +QUnit.test("PriorityQueue - Execute test", function (assert) +{ + var queue = new ds.PriorityQueue(); + queue.enqueue(4, 0); + queue.enqueue(3, 2); + var callback = function (item) + { + return item * 2; + }; + queue.execute(callback); + assert.deepEqual(queue.getItem(0), 0, "Execute for item 0"); + assert.deepEqual(queue.getItem(1), 4, "Execute for item 1"); +}); + +QUnit.test("PriorityQueue - Remove test", function (assert) +{ + var queue = new ds.PriorityQueue(); + queue.enqueue(4, 0); + queue.enqueue(3, 1); + queue.enqueue(2, 2); + queue.enqueue(1, 3); + queue.enqueue(0, 4); + for (var i = 0; i < 5; i++) + assert.deepEqual(queue.getItem(i), i, "Check queue correctness"); + queue.changePriority(3, 8); + for (var j = 0; j < 5; j++) + { + if (!j) + assert.deepEqual(queue.getItem(j), 3, "Check increase priority"); + else if (j < 4) + assert.deepEqual(queue.getItem(j), j - 1, "Check increase priority"); + else + assert.deepEqual(queue.getItem(j), j, "Check increase priority"); + } + queue.changePriority(3, -4); + for (var k = 0; k < 5; k++) + { + if (!k) + assert.deepEqual(queue.getItem(k), 3, "Check decrease priority"); + else if (k < 3) + assert.deepEqual(queue.getItem(k), k - 1, "Check decrease priority"); + else if (k === 3) + assert.deepEqual(queue.getItem(k), 4, "Check decrease priority"); + else + assert.deepEqual(queue.getItem(k), 2, "Check decrease priority"); + } + +}); + +QUnit.test("PriorityQueue - Filter test", function (assert) +{ + var queue = new ds.PriorityQueue(); + const length = 100; + + for (var i = 0; i < length; i++) + queue.enqueue(i, i); + + var result = queue.filter(function (item) + { + return 1 - item % 2; + }); + + assert.deepEqual(result[0], 98, "Filter of the even values"); + assert.deepEqual(result[result.length - 1], 0, "Filter on the even values"); +}); + +QUnit.test("PriorityQueue - Clone test", function (assert) +{ + var queue = new ds.PriorityQueue(); + for (var i = 0; i < 10; i++) + queue.enqueue(i, i); + var clone = queue.clone(); + assert.deepEqual(clone.multiDequeue(10), [9, 8, 7, 6, 5, 4, 3, 2, 1, 0], "Clone of the queue"); +}); + +QUnit.test("PriorityQueue - Clone distinct test", function (assert) +{ + var queue = new ds.PriorityQueue(); + for (var i = 0; i < 40; i++) + queue.enqueue(i % 20, i % 10); + var clone = queue.cloneDistinct(); + assert.deepEqual(clone.multiDequeue(10), [9, 8, 7, 6, 5, 4, 3, 2, 1, 0], "Clone of the queue"); +}); \ No newline at end of file diff --git a/Tests/Queue_Test.js b/Tests/Queue_Test.js deleted file mode 100644 index 1081ded..0000000 --- a/Tests/Queue_Test.js +++ /dev/null @@ -1,220 +0,0 @@ -/** - * Created by Battistella Stefano on 31/03/14. - */ - -test("Queue - Init test", function () { - var queue = new Queue(0, 2, 4, 6); - deepEqual(queue.multiDequeue(4), [0, 2, 4, 6], "Initializing"); - queue = new Queue(0); - deepEqual(queue.multiDequeue(4), [0], "Initializing"); -}); - -test("Queue - Init range test", function () { - var queue = new Queue(Range(0, 6, 2)); - deepEqual(queue.multiDequeue(4), [0, 2, 4, 6], "Initializing"); -}); - -test("Queue - Enqueue test", function () { - var queue = new Queue(); - queue.enqueue(0); - deepEqual(queue.peek(), 0, "Enqueue 0"); - queue.enqueue(2); - deepEqual(queue.getItem(0), 0, "Enqueue 2"); - deepEqual(queue.getItem(1), 2, "Enqueue 2"); -}); - -test("Queue - MultiEnqueue test", function () { - var queue = new Queue(); - queue.multiEnqueue([0, 2]); - deepEqual(queue.multiDequeue(2), [0, 2], "MultiEnqueue 2 items"); - queue.multiEnqueue([2]); - queue.multiEnqueue([4, 5, 8]); - deepEqual(queue.multiDequeue(4), [2, 4, 5, 8], "MultiDequeue 4 items"); - queue.multiEnqueue([]); - deepEqual(queue.multiDequeue(1), [], "MultiEnqueue 0 items"); -}); - -test("Queue - Dequeue test", function () { - var queue = new Queue(); - queue.enqueue(0); - queue.enqueue(2); - deepEqual(queue.dequeue(), 0, "Dequeue"); - deepEqual(queue.dequeue(), 2, "Dequeue"); - deepEqual(queue.dequeue(), undefined, "Check length if too much dequeue"); -}); - -test("Queue - MultiDequeue test", function () { - var queue = new Queue(); - queue.enqueue(0); - queue.enqueue(2); - deepEqual(queue.multiDequeue(1), [0], "MultiDequeue 1 time"); - queue.enqueue(4); - queue.enqueue(5); - queue.enqueue(8); - deepEqual(queue.multiDequeue(7), [2, 4, 5, 8], "MultiDequeue 7 times"); - deepEqual(queue.multiDequeue(1), [], "MultiDequeue 1 time with queue empty"); -}); - -test("Queue - Remove test", function () { - var queue = new Queue(); - queue.enqueue(0); - queue.enqueue(2); - queue.enqueue(4); - queue.enqueue(5); - queue.enqueue(8); - queue.remove(2, 2); - deepEqual(queue.multiDequeue(3), [0, 2, 8], "Remove from position 2 for 2"); -}); - -test("Queue - Iterator test", function () { - var queue = new Queue(); - for (var i = 0; i < 10; i++) - queue.enqueue(i); - var j = 0; - var it = queue.getIterator(); - for (it.first(); !it.isDone(); it.next(), j++) - deepEqual(it.getItem(), j, "Get next item " + j); - j--; - for (it.last(); !it.isDone(); it.previous(), j--) - deepEqual(it.getItem(), j, "Get previous item " + j); -}); - -test("Queue - Get length test", function () { - var queue = new Queue(); - deepEqual(queue.getLength(), 0, "Length 0"); - queue.enqueue(0); - deepEqual(queue.getLength(), 1, "Length 1"); - queue.enqueue(2); - deepEqual(queue.getLength(), 2, "Length 2"); - queue.dequeue(); - queue.dequeue(); - deepEqual(queue.getLength(), 0, "Length 0"); - -}); - -test("Queue - Peek test", function () { - var queue = new Queue(); - queue.enqueue(0); - deepEqual(queue.peek(), 0, "Peek 0"); - queue.enqueue(2); - deepEqual(queue.peek(), 0, "Peek 0"); -}); - -test("Queue - Clear test", function () { - var queue = new Queue(); - queue.enqueue(0); - queue.enqueue(2); - queue.clear(); - deepEqual(queue.isEmpty(), true, "Clear queue"); -}); - -test("Queue - Is empty test", function () { - var queue = new Queue(); - queue.enqueue(0); - queue.enqueue(2); - deepEqual(queue.isEmpty(), false, "Is not empty"); - queue.clear(); - deepEqual(queue.isEmpty(), true, "Is empty"); -}); - -test("Queue - Contains test", function () { - var queue = new Queue(); - queue.enqueue(0); - queue.enqueue(2); - deepEqual(queue.contains(0), true, "Contains 0"); - deepEqual(queue.contains(2), true, "Contains 2"); - deepEqual(queue.contains(1), false, "Not contains 1"); - var callback = function (item) { - return item > 0; - }; - deepEqual(queue.contains(null, callback), true, "Contains a value > 0"); - callback = function (item) { - return item < 0; - }; - deepEqual(queue.contains(null, callback), false, "Contains a value < 0"); -}); - -test("Queue - Execute test", function () { - var queue = new Queue(); - queue.enqueue(0); - queue.enqueue(2); - var callback = function (item) { - return item * 2; - }; - queue.execute(callback); - deepEqual(queue.getItem(0), 0, "Execute for item 0"); - deepEqual(queue.getItem(1), 4, "Execute for item 1"); -}); - -test("Queue - Index of test", function () { - var queue = new Queue(); - for (var i = 0; i < 10; i++) - queue.enqueue(i); - var callback = function (item) { - return !(item % 2) && item > 5; - }; - deepEqual(queue.indexOf(0), 0, "Index of 0"); - deepEqual(queue.indexOf(15), -1, "Index of 15"); - deepEqual(queue.indexOf(5), 5, "Index of 5"); - deepEqual(queue.indexOf(null, callback), 6, "Index of the first even number greater than 5"); -}); - -test("Queue - Last index of test", function () { - var queue = new Queue(); - for (var i = 0; i < 10; i++) - queue.enqueue(i); - var callback = function (item) { - return !(item % 2) && item > 5; - }; - deepEqual(queue.lastIndexOf(0), 0, "Last index of 0"); - deepEqual(queue.lastIndexOf(15), -1, "Last index of 15"); - deepEqual(queue.lastIndexOf(5), 5, "Last index of 5"); - deepEqual(queue.lastIndexOf(null, callback), 8, "Index of the last even number greater than 5"); -}); - -test("Queue - Indexes of test", function () { - var queue = new Queue(); - for (var i = 0; i < 30; i++) - queue.enqueue(i % 10); - var callback = function (item) { - return !(item % 2) && item > 5; - }; - deepEqual(queue.allIndexesOf(0), [0, 10, 20], "Indexes of 0"); - deepEqual(queue.allIndexesOf(15), [], "Indexes of 15"); - deepEqual(queue.allIndexesOf(5), [5, 15, 25], "Indexes of 5"); - deepEqual(queue.allIndexesOf(null, callback), [6, 8, 16, 18, 26, 28], "Indexes of the even numbers greater than 5"); -}); - -test("Queue - Clone test", function () { - var queue = new Queue(); - for (var i = 0; i < 10; i++) - queue.enqueue(i); - var clone = queue.clone(); - var it = clone.getIterator(); - var j = 0; - for (it.first(); !it.isDone(); it.next(), j++) - deepEqual(it.getItem(), j, "Clone of the queue"); -}); - -test("Queue - Clone distinct test", function () { - var queue = new Queue(); - for (var i = 0; i < 20; i++) - queue.enqueue(i % 10); - var clone = queue.cloneDistinct(); - deepEqual(clone.allIndexesOf(2), [2], "Clone of the queue"); -}); - -test("Queue - Filter test", function () { - var queue = new Queue(); - const length = 100; - - for (var i = 0; i < length; i++) - queue.enqueue(i); - - var result = queue.filter(function (item) { - return 1 - item % 2; - }); - - deepEqual(result[0], 0, "Filter of the even values"); - deepEqual(result[result.length - 1], 98, "Filter on the even values"); -}); \ No newline at end of file diff --git a/Tests/Queue_Test.ts b/Tests/Queue_Test.ts new file mode 100644 index 0000000..b5c6ee6 --- /dev/null +++ b/Tests/Queue_Test.ts @@ -0,0 +1,247 @@ +/** + * Created by Battistella Stefano on 31/03/14. + */ + +QUnit.test("Queue - Init test", function (assert) +{ + var queue = new ds.Queue(0, 2, 4, 6); + assert.deepEqual(queue.multiDequeue(4), [0, 2, 4, 6], "Initializing"); + queue = new ds.Queue(0); + assert.deepEqual(queue.multiDequeue(4), [0], "Initializing"); +}); + +QUnit.test("Queue - Init range test", function (assert) +{ + var queue = new ds.Queue(ds.Range(0, 6, 2)); + assert.deepEqual(queue.multiDequeue(4), [0, 2, 4, 6], "Initializing"); +}); + +QUnit.test("Queue - Enqueue test", function (assert) +{ + var queue = new ds.Queue(); + queue.enqueue(0); + assert.deepEqual(queue.peek(), 0, "Enqueue 0"); + queue.enqueue(2); + assert.deepEqual(queue.getItem(0), 0, "Enqueue 2"); + assert.deepEqual(queue.getItem(1), 2, "Enqueue 2"); +}); + +QUnit.test("Queue - MultiEnqueue test", function (assert) +{ + var queue = new ds.Queue(); + queue.multiEnqueue([0, 2]); + assert.deepEqual(queue.multiDequeue(2), [0, 2], "MultiEnqueue 2 items"); + queue.multiEnqueue([2]); + queue.multiEnqueue([4, 5, 8]); + assert.deepEqual(queue.multiDequeue(4), [2, 4, 5, 8], "MultiDequeue 4 items"); + queue.multiEnqueue([]); + assert.deepEqual(queue.multiDequeue(1), [], "MultiEnqueue 0 items"); +}); + +QUnit.test("Queue - Dequeue test", function (assert) +{ + var queue = new ds.Queue(); + queue.enqueue(0); + queue.enqueue(2); + assert.deepEqual(queue.dequeue(), 0, "Dequeue"); + assert.deepEqual(queue.dequeue(), 2, "Dequeue"); + assert.deepEqual(queue.dequeue(), undefined, "Check length if too much dequeue"); +}); + +QUnit.test("Queue - MultiDequeue test", function (assert) +{ + var queue = new ds.Queue(); + queue.enqueue(0); + queue.enqueue(2); + assert.deepEqual(queue.multiDequeue(1), [0], "MultiDequeue 1 time"); + queue.enqueue(4); + queue.enqueue(5); + queue.enqueue(8); + assert.deepEqual(queue.multiDequeue(7), [2, 4, 5, 8], "MultiDequeue 7 times"); + assert.deepEqual(queue.multiDequeue(1), [], "MultiDequeue 1 time with queue empty"); +}); + +QUnit.test("Queue - Remove test", function (assert) +{ + var queue = new ds.Queue(); + queue.enqueue(0); + queue.enqueue(2); + queue.enqueue(4); + queue.enqueue(5); + queue.enqueue(8); + queue.remove(2, 2); + assert.deepEqual(queue.multiDequeue(3), [0, 2, 8], "Remove from position 2 for 2"); +}); + +QUnit.test("Queue - Iterator test", function (assert) +{ + var queue = new ds.Queue(); + for (var i = 0; i < 10; i++) + queue.enqueue(i); + var j = 0; + var it = queue.getIterator(); + for (it.first(); !it.isDone(); it.next(), j++) + assert.deepEqual(it.getItem(), j, "Get next item " + j); + j--; + for (it.last(); !it.isDone(); it.previous(), j--) + assert.deepEqual(it.getItem(), j, "Get previous item " + j); +}); + +QUnit.test("Queue - Get length test", function (assert) +{ + var queue = new ds.Queue(); + assert.deepEqual(queue.getLength(), 0, "Length 0"); + queue.enqueue(0); + assert.deepEqual(queue.getLength(), 1, "Length 1"); + queue.enqueue(2); + assert.deepEqual(queue.getLength(), 2, "Length 2"); + queue.dequeue(); + queue.dequeue(); + assert.deepEqual(queue.getLength(), 0, "Length 0"); + +}); + +QUnit.test("Queue - Peek test", function (assert) +{ + var queue = new ds.Queue(); + queue.enqueue(0); + assert.deepEqual(queue.peek(), 0, "Peek 0"); + queue.enqueue(2); + assert.deepEqual(queue.peek(), 0, "Peek 0"); +}); + +QUnit.test("Queue - Clear test", function (assert) +{ + var queue = new ds.Queue(); + queue.enqueue(0); + queue.enqueue(2); + queue.clear(); + assert.deepEqual(queue.isEmpty(), true, "Clear queue"); +}); + +QUnit.test("Queue - Is empty test", function (assert) +{ + var queue = new ds.Queue(); + queue.enqueue(0); + queue.enqueue(2); + assert.deepEqual(queue.isEmpty(), false, "Is not empty"); + queue.clear(); + assert.deepEqual(queue.isEmpty(), true, "Is empty"); +}); + +QUnit.test("Queue - Contains test", function (assert) +{ + var queue = new ds.Queue(); + queue.enqueue(0); + queue.enqueue(2); + assert.deepEqual(queue.contains(0), true, "Contains 0"); + assert.deepEqual(queue.contains(2), true, "Contains 2"); + assert.deepEqual(queue.contains(1), false, "Not contains 1"); + var callback = function (item) + { + return item > 0; + }; + assert.deepEqual(queue.contains(null, callback), true, "Contains a value > 0"); + callback = function (item) + { + return item < 0; + }; + assert.deepEqual(queue.contains(null, callback), false, "Contains a value < 0"); +}); + +QUnit.test("Queue - Execute test", function (assert) +{ + var queue = new ds.Queue(); + queue.enqueue(0); + queue.enqueue(2); + var callback = function (item) + { + return item * 2; + }; + queue.execute(callback); + assert.deepEqual(queue.getItem(0), 0, "Execute for item 0"); + assert.deepEqual(queue.getItem(1), 4, "Execute for item 1"); +}); + +QUnit.test("Queue - Index of test", function (assert) +{ + var queue = new ds.Queue(); + for (var i = 0; i < 10; i++) + queue.enqueue(i); + var callback = function (item) + { + return !(item % 2) && item > 5; + }; + assert.deepEqual(queue.indexOf(0), 0, "Index of 0"); + assert.deepEqual(queue.indexOf(15), -1, "Index of 15"); + assert.deepEqual(queue.indexOf(5), 5, "Index of 5"); + assert.deepEqual(queue.indexOf(null, callback), 6, "Index of the first even number greater than 5"); +}); + +QUnit.test("Queue - Last index of test", function (assert) +{ + var queue = new ds.Queue(); + for (var i = 0; i < 10; i++) + queue.enqueue(i); + var callback = function (item) + { + return !(item % 2) && item > 5; + }; + assert.deepEqual(queue.lastIndexOf(0), 0, "Last index of 0"); + assert.deepEqual(queue.lastIndexOf(15), -1, "Last index of 15"); + assert.deepEqual(queue.lastIndexOf(5), 5, "Last index of 5"); + assert.deepEqual(queue.lastIndexOf(null, callback), 8, "Index of the last even number greater than 5"); +}); + +QUnit.test("Queue - Indexes of test", function (assert) +{ + var queue = new ds.Queue(); + for (var i = 0; i < 30; i++) + queue.enqueue(i % 10); + var callback = function (item) + { + return !(item % 2) && item > 5; + }; + assert.deepEqual(queue.allIndexesOf(0), [0, 10, 20], "Indexes of 0"); + assert.deepEqual(queue.allIndexesOf(15), [], "Indexes of 15"); + assert.deepEqual(queue.allIndexesOf(5), [5, 15, 25], "Indexes of 5"); + assert.deepEqual(queue.allIndexesOf(null, callback), [6, 8, 16, 18, 26, 28], "Indexes of the even numbers greater than 5"); +}); + +QUnit.test("Queue - Clone test", function (assert) +{ + var queue = new ds.Queue(); + for (var i = 0; i < 10; i++) + queue.enqueue(i); + var clone = queue.clone(); + var it = clone.getIterator(); + var j = 0; + for (it.first(); !it.isDone(); it.next(), j++) + assert.deepEqual(it.getItem(), j, "Clone of the queue"); +}); + +QUnit.test("Queue - Clone distinct test", function (assert) +{ + var queue = new ds.Queue(); + for (var i = 0; i < 20; i++) + queue.enqueue(i % 10); + var clone = queue.cloneDistinct(); + assert.deepEqual(clone.allIndexesOf(2), [2], "Clone of the queue"); +}); + +QUnit.test("Queue - Filter test", function (assert) +{ + var queue = new ds.Queue(); + const length = 100; + + for (var i = 0; i < length; i++) + queue.enqueue(i); + + var result = queue.filter(function (item) + { + return Boolean(1 - item % 2); + }); + + assert.deepEqual(result[0], 0, "Filter of the even values"); + assert.deepEqual(result[result.length - 1], 98, "Filter on the even values"); +}); \ No newline at end of file diff --git a/Tests/RBTreeList_Test.js b/Tests/RBTreeList_Test.js deleted file mode 100644 index f1f96ea..0000000 --- a/Tests/RBTreeList_Test.js +++ /dev/null @@ -1,207 +0,0 @@ -/** - * Created by Stefano on 06/04/14. - */ - -test("RBTreeList - Insert test", function () { - var tree = new RBTreeList(); - var keys = []; - for (var i = 0; i < 20; i++) { - keys.push(Math.random()); - tree.insert(keys[i], i); - } - for (var j = 0; j < 20; j++) - deepEqual(tree.search(keys[j]), j, "Insert node"); -}); - -test("RBTreeList - Minimum test", function () { - var tree = new RBTreeList(); - var keys = []; - var min = 10; - for (var i = 0; i < 20; i++) { - keys.push(Math.random()); - tree.insert(keys[i], i); - if (keys[i] < min) - min = keys[i]; - } - deepEqual(tree.minimum().item, tree.search(min), "Minimum"); -}); - -test("RBTreeList - Maximum test", function () { - var tree = new RBTreeList(); - var keys = []; - var max = -1; - for (var i = 0; i < 20; i++) { - keys.push(Math.random()); - tree.insert(keys[i], i); - if (keys[i] > max) - max = keys[i]; - } - deepEqual(tree.maximum().item, tree.search(max), "Maximum"); -}); - -test("RBTreeList - Successor test", function () { - var tree = new RBTreeList(); - for (var i = 0; i < 20; i++) - tree.insert(i, i); - var it = tree.getIterator(); - var j = 1; - for (it.first(); !it.isDone(); it.next(), j++) { - var successor = tree.successor(it.getNode()); - if (successor) - deepEqual(successor.item, j, "Successor"); - else - deepEqual(successor, null, "No successor"); - } -}); - -test("RBTreeList - Predecessor test", function () { - var tree = new RBTreeList(); - for (var i = 0; i < 20; i++) - tree.insert(i, i); - var it = tree.getIterator(); - var j = 18; - for (it.last(); !it.isDone(); it.previous(), j--) { - var predecessor = tree.predecessor(it.getNode()); - if (predecessor) - deepEqual(predecessor.item, j, "Predecessor"); - else - deepEqual(predecessor, null, "No predecessor"); - } -}); - -test("RBTreeList - Delete node test", function () { - var tree = new RBTreeList(); - for (var i = 0; i < 20; i++) - tree.insert(i, i); - var j = 0; - while (tree.minimum()) { - deepEqual(tree.minimum().item, j, "Deletion"); - tree.deleteNode(tree.minimum()); - j++; - } -}); - -test("RBTreeList - To array test", function () { - var tree = new RBTreeList(); - for (var i = 0; i < 5; i++) - tree.insert(i, i); - deepEqual(tree.toArray(), [0, 1, 2, 3, 4], "To array"); -}); - -test("RBTreeList - Filter test", function () { - var tree = new RBTreeList(); - - for (var i = 0; i < 100; i++) - tree.insert(i, i); - - var result = tree.filter(function (item) { - return 1 - item % 2; - }); - - deepEqual(result[0], 0, "Filter of the even values"); - deepEqual(result[result.length - 1], 98, "Filter on the even values"); -}); - -test("RBTreeList - Clear test", function () { - var tree = new RBTreeList(); - tree.insert(0, 0); - tree.insert(2, 2); - tree.clear(); - deepEqual(tree.isEmpty(), true, "Clear tree"); -}); - -test("RBTreeList - Is empty test", function () { - var tree = new RBTreeList(); - tree.insert(0, 0); - tree.insert(2, 2); - deepEqual(tree.isEmpty(), false, "Is not empty"); - tree.clear(); - deepEqual(tree.isEmpty(), true, "Is empty"); -}); - -test("RBTreeList - Contains test", function () { - var tree = new RBTreeList(); - tree.insert(0, 0); - tree.insert(2, 2); - deepEqual(tree.contains(0), true, "Contains 0"); - deepEqual(tree.contains(2), true, "Contains 2"); - deepEqual(tree.contains(1), false, "Not contains 1"); - var callback = function (item) { - return item > 0; - }; - deepEqual(tree.fullContains(callback), true, "Contains a value > 0"); - callback = function (item) { - return item < 0; - }; - deepEqual(tree.fullContains(callback), false, "Contains a value < 0"); -}); - -test("RBTreeList - Execute test", function () { - var tree = new RBTreeList(); - tree.insert(0, 0); - tree.insert(2, 2); - var callback = function (item) { - return item * 2; - }; - tree.execute(callback); - deepEqual(tree.search(0), 0, "Execute for key 0"); - deepEqual(tree.search(2), 4, "Execute for key 1"); -}); - -test("RBTreeList - Index of test", function () { - var tree = new RBTreeList(); - for (var i = 0; i < 10; i++) - tree.insert(i, i); - var callback = function (item) { - return !(item % 2) && item > 5; - }; - deepEqual(tree.indexOf(0), 0, "Index of 0"); - deepEqual(tree.indexOf(15), -1, "Index of 15"); - deepEqual(tree.indexOf(5), 5, "Index of 5"); - deepEqual(tree.indexOf(null, callback), 6, "Index of the first even number greater than 5"); -}); - -test("RBTreeList - Last index of test", function () { - var tree = new RBTreeList(); - for (var i = 0; i < 10; i++) - tree.insert(i, i); - var callback = function (item) { - return !(item % 2) && item > 5; - }; - deepEqual(tree.lastIndexOf(0), 0, "Last index of 0"); - deepEqual(tree.lastIndexOf(15), -1, "Last index of 15"); - deepEqual(tree.lastIndexOf(5), 5, "Last index of 5"); - deepEqual(tree.lastIndexOf(null, callback), 8, "Index of the last even number greater than 5"); -}); - -test("RBTreeList - Indexes of test", function () { - var tree = new RBTreeList(); - for (var i = 0; i < 30; i++) - tree.insert(i, i % 10); - var callback = function (item) { - return !(item % 2) && item > 5; - }; - deepEqual(tree.allIndexesOf(0), [0, 10, 20], "Indexes of 0"); - deepEqual(tree.allIndexesOf(15), [], "Indexes of 15"); - deepEqual(tree.allIndexesOf(5), [5, 15, 25], "Indexes of 5"); - deepEqual(tree.allIndexesOf(null, callback), [6, 8, 16, 18, 26, 28], "Indexes of the even numbers greater than 5"); -}); - -test("RBTreeList - Clone test", function () { - var tree = new RBTreeList(); - for (var i = 0; i < 10; i++) - tree.insert(i, i); - var clone = tree.clone(); - var it = clone.getIterator(); - var j = 0; - for (it.first(); !it.isDone(); it.next(), j++) - deepEqual(it.getItem(), j, "Clone of the tree"); -}); - -test("RBTreeList - Clone distinct test", function () { - var tree = new RBTreeList(); - for (var i = 0; i < 20; i++) - tree.insert(i % 10, i % 10); - var clone = tree.cloneDistinct(); - deepEqual(clone.allIndexesOf(2), [2], "Clone of the tree"); -}); \ No newline at end of file diff --git a/Tests/RBTreeList_Test.ts b/Tests/RBTreeList_Test.ts new file mode 100644 index 0000000..9feb082 --- /dev/null +++ b/Tests/RBTreeList_Test.ts @@ -0,0 +1,237 @@ +/** + * Created by Stefano on 06/04/14. + */ + +QUnit.test("RBTreeList - Insert test", function (assert) +{ + var tree = new ds.RBTreeList(); + var keys = []; + for (var i = 0; i < 20; i++) + { + keys.push(Math.random()); + tree.insert(keys[i], i); + } + for (var j = 0; j < 20; j++) + assert.deepEqual(tree.search(keys[j]), j, "Insert node"); +}); + +QUnit.test("RBTreeList - Minimum test", function (assert) +{ + var tree = new ds.RBTreeList(); + var keys = []; + var min = 10; + for (var i = 0; i < 20; i++) + { + keys.push(Math.random()); + tree.insert(keys[i], i); + if (keys[i] < min) + min = keys[i]; + } + assert.deepEqual(tree.minimum().item, tree.search(min), "Minimum"); +}); + +QUnit.test("RBTreeList - Maximum test", function (assert) +{ + var tree = new ds.RBTreeList(); + var keys = []; + var max = -1; + for (var i = 0; i < 20; i++) + { + keys.push(Math.random()); + tree.insert(keys[i], i); + if (keys[i] > max) + max = keys[i]; + } + assert.deepEqual(tree.maximum().item, tree.search(max), "Maximum"); +}); + +QUnit.test("RBTreeList - Successor test", function (assert) +{ + var tree = new ds.RBTreeList(); + for (var i = 0; i < 20; i++) + tree.insert(i, i); + var it = tree.getIterator(); + var j = 1; + for (it.first(); !it.isDone(); it.next(), j++) + { + var successor = tree.successor(it.getNode()); + if (successor) + assert.deepEqual(successor.item, j, "Successor"); + else + assert.deepEqual(successor, null, "No successor"); + } +}); + +QUnit.test("RBTreeList - Predecessor test", function (assert) +{ + var tree = new ds.RBTreeList(); + for (var i = 0; i < 20; i++) + tree.insert(i, i); + var it = tree.getIterator(); + var j = 18; + for (it.last(); !it.isDone(); it.previous(), j--) + { + var predecessor = tree.predecessor(it.getNode()); + if (predecessor) + assert.deepEqual(predecessor.item, j, "Predecessor"); + else + assert.deepEqual(predecessor, null, "No predecessor"); + } +}); + +QUnit.test("RBTreeList - Delete node test", function (assert) +{ + var tree = new ds.RBTreeList(); + for (var i = 0; i < 20; i++) + tree.insert(i, i); + var j = 0; + while (tree.minimum()) + { + assert.deepEqual(tree.minimum().item, j, "Deletion"); + tree.deleteNode(tree.minimum()); + j++; + } +}); + +QUnit.test("RBTreeList - To array test", function (assert) +{ + var tree = new ds.RBTreeList(); + for (var i = 0; i < 5; i++) + tree.insert(i, i); + assert.deepEqual(tree.toArray(), [0, 1, 2, 3, 4], "To array"); +}); + +QUnit.test("RBTreeList - Filter test", function (assert) +{ + var tree = new ds.RBTreeList(); + + for (var i = 0; i < 100; i++) + tree.insert(i, i); + + var result = tree.filter(function (item) + { + return Boolean(1 - item % 2); + }); + + assert.deepEqual(result[0], 0, "Filter of the even values"); + assert.deepEqual(result[result.length - 1], 98, "Filter on the even values"); +}); + +QUnit.test("RBTreeList - Clear test", function (assert) +{ + var tree = new ds.RBTreeList(); + tree.insert(0, 0); + tree.insert(2, 2); + tree.clear(); + assert.deepEqual(tree.isEmpty(), true, "Clear tree"); +}); + +QUnit.test("RBTreeList - Is empty test", function (assert) +{ + var tree = new ds.RBTreeList(); + tree.insert(0, 0); + tree.insert(2, 2); + assert.deepEqual(tree.isEmpty(), false, "Is not empty"); + tree.clear(); + assert.deepEqual(tree.isEmpty(), true, "Is empty"); +}); + +QUnit.test("RBTreeList - Contains test", function (assert) +{ + var tree = new ds.RBTreeList(); + tree.insert(0, 0); + tree.insert(2, 2); + assert.deepEqual(tree.contains(0), true, "Contains 0"); + assert.deepEqual(tree.contains(2), true, "Contains 2"); + assert.deepEqual(tree.contains(1), false, "Not contains 1"); + var callback = function (item) + { + return item > 0; + }; + assert.deepEqual(tree.fullContains(callback), true, "Contains a value > 0"); + callback = function (item) + { + return item < 0; + }; + assert.deepEqual(tree.fullContains(callback), false, "Contains a value < 0"); +}); + +QUnit.test("RBTreeList - Execute test", function (assert) +{ + var tree = new ds.RBTreeList(); + tree.insert(0, 0); + tree.insert(2, 2); + var callback = function (item) + { + return item * 2; + }; + tree.execute(callback); + assert.deepEqual(tree.search(0), 0, "Execute for key 0"); + assert.deepEqual(tree.search(2), 4, "Execute for key 1"); +}); + +QUnit.test("RBTreeList - Index of test", function (assert) +{ + var tree = new ds.RBTreeList(); + for (var i = 0; i < 10; i++) + tree.insert(i, i); + var callback = function (item) + { + return !(item % 2) && item > 5; + }; + assert.deepEqual(tree.indexOf(0), 0, "Index of 0"); + assert.deepEqual(tree.indexOf(15), -1, "Index of 15"); + assert.deepEqual(tree.indexOf(5), 5, "Index of 5"); + assert.deepEqual(tree.indexOf(null, callback), 6, "Index of the first even number greater than 5"); +}); + +QUnit.test("RBTreeList - Last index of test", function (assert) +{ + var tree = new ds.RBTreeList(); + for (var i = 0; i < 10; i++) + tree.insert(i, i); + var callback = function (item) + { + return !(item % 2) && item > 5; + }; + assert.deepEqual(tree.lastIndexOf(0), 0, "Last index of 0"); + assert.deepEqual(tree.lastIndexOf(15), -1, "Last index of 15"); + assert.deepEqual(tree.lastIndexOf(5), 5, "Last index of 5"); + assert.deepEqual(tree.lastIndexOf(null, callback), 8, "Index of the last even number greater than 5"); +}); + +QUnit.test("RBTreeList - Indexes of test", function (assert) +{ + var tree = new ds.RBTreeList(); + for (var i = 0; i < 30; i++) + tree.insert(i, i % 10); + var callback = function (item) + { + return !(item % 2) && item > 5; + }; + assert.deepEqual(tree.allIndexesOf(0), [0, 10, 20], "Indexes of 0"); + assert.deepEqual(tree.allIndexesOf(15), [], "Indexes of 15"); + assert.deepEqual(tree.allIndexesOf(5), [5, 15, 25], "Indexes of 5"); + assert.deepEqual(tree.allIndexesOf(null, callback), [6, 8, 16, 18, 26, 28], "Indexes of the even numbers greater than 5"); +}); + +QUnit.test("RBTreeList - Clone test", function (assert) +{ + var tree = new ds.RBTreeList(); + for (var i = 0; i < 10; i++) + tree.insert(i, i); + var clone = tree.clone(); + var it = clone.getIterator(); + var j = 0; + for (it.first(); !it.isDone(); it.next(), j++) + assert.deepEqual(it.getItem(), j, "Clone of the tree"); +}); + +QUnit.test("RBTreeList - Clone distinct test", function (assert) +{ + var tree = new ds.RBTreeList(); + for (var i = 0; i < 20; i++) + tree.insert(i % 10, i % 10); + var clone = tree.cloneDistinct(); + assert.deepEqual(clone.allIndexesOf(2), [2], "Clone of the tree"); +}); \ No newline at end of file diff --git a/Tests/RBTree_Test.js b/Tests/RBTree_Test.js deleted file mode 100644 index 404636c..0000000 --- a/Tests/RBTree_Test.js +++ /dev/null @@ -1,211 +0,0 @@ -/** - * Created by Stefano on 06/04/14. - */ - -test("RBTree - Insert test", function () { - var tree = new RBTree(); - var keys = []; - for (var i = 0; i < 20; i++) { - keys.push(Math.random()); - tree.insert(keys[i], keys[i]); - } - for (var j = 0; j < 20; j++) - deepEqual(tree.search(keys[j]), keys[j], "Insert node"); - keys.sort(); - for (var k = 0; k < 20; k++) - deepEqual(tree.getItem(k), keys[k], "Insert node"); -}); - -test("RBTree - Minimum test", function () { - var tree = new RBTree(); - var keys = []; - var min = 10; - for (var i = 0; i < 20; i++) { - keys.push(Math.random()); - tree.insert(keys[i], i); - if (keys[i] < min) - min = keys[i]; - } - deepEqual(tree.minimum().item, tree.search(min), "Minimum"); -}); - -test("RBTree - Maximum test", function () { - var tree = new RBTree(); - var keys = []; - var max = -1; - for (var i = 0; i < 20; i++) { - keys.push(Math.random()); - tree.insert(keys[i], i); - if (keys[i] > max) - max = keys[i]; - } - deepEqual(tree.maximum().item, tree.search(max), "Maximum"); -}); - -test("RBTree - Successor test", function () { - var tree = new RBTree(); - for (var i = 0; i < 20; i++) - tree.insert(i, i); - var it = tree.getIterator(); - var j = 1; - for (it.first(); !it.isDone(); it.next(), j++) { - var successor = tree.successor(it.getNode()); - if (successor) - deepEqual(successor.item, j, "Successor"); - else - deepEqual(successor, null, "No successor"); - } -}); - -test("RBTree - Predecessor test", function () { - var tree = new RBTree(); - for (var i = 0; i < 20; i++) - tree.insert(i, i); - var it = tree.getIterator(); - var j = 18; - for (it.last(); !it.isDone(); it.previous(), j--) { - var predecessor = tree.predecessor(it.getNode()); - if (predecessor) - deepEqual(predecessor.item, j, "Predecessor"); - else - deepEqual(predecessor, null, "No predecessor"); - } -}); - -test("RBTree - Delete node test", function () { - var tree = new RBTree(); - for (var i = 0; i < 20; i++) - tree.insert(i, i); - var j = 0; - while (tree.minimum()) { - deepEqual(tree.minimum().item, j, "Deletion"); - tree.deleteNode(tree.minimum()); - j++; - } -}); - -test("RBTree - To array test", function () { - var tree = new RBTree(); - for (var i = 0; i < 5; i++) - tree.insert(i, i); - deepEqual(tree.toArray(), [0, 1, 2, 3, 4], "To array"); -}); - -test("RBTree - Filter test", function () { - var tree = new RBTree(); - const length = 100; - - for (var i = 0; i < length; i++) - tree.insert(i, i); - - var result = tree.filter(function (item) { - return 1 - item % 2; - }); - - deepEqual(result[0], 0, "Filter of the even values"); - deepEqual(result[result.length - 1], 98, "Filter on the even values"); -}); - -test("RBTree - Clear test", function () { - var tree = new RBTreeList(); - tree.insert(0, 0); - tree.insert(2, 2); - tree.clear(); - deepEqual(tree.isEmpty(), true, "Clear tree"); -}); - -test("RBTree - Is empty test", function () { - var tree = new RBTree(); - tree.insert(0, 0); - tree.insert(2, 2); - deepEqual(tree.isEmpty(), false, "Is not empty"); - tree.clear(); - deepEqual(tree.isEmpty(), true, "Is empty"); -}); - -test("RBTree - Contains test", function () { - var tree = new RBTree(); - tree.insert(0, 0); - tree.insert(2, 2); - deepEqual(tree.contains(0), true, "Contains 0"); - deepEqual(tree.contains(2), true, "Contains 2"); - deepEqual(tree.contains(1), false, "Not contains 1"); - var callback = function (item) { - return item > 0; - }; - deepEqual(tree.fullContains(callback), true, "Contains a value > 0"); - callback = function (item) { - return item < 0; - }; - deepEqual(tree.fullContains(callback), false, "Contains a value < 0"); -}); - -test("RBTree - Execute test", function () { - var tree = new RBTree(); - tree.insert(0, 0); - tree.insert(2, 2); - var callback = function (item) { - return item * 2; - }; - tree.execute(callback); - deepEqual(tree.search(0), 0, "Execute for key 0"); - deepEqual(tree.search(2), 4, "Execute for key 1"); -}); - -test("RBTree - Index of test", function () { - var tree = new RBTree(); - for (var i = 0; i < 10; i++) - tree.insert(i, i); - var callback = function (item) { - return !(item % 2) && item > 5; - }; - deepEqual(tree.indexOf(0), 0, "Index of 0"); - deepEqual(tree.indexOf(15), -1, "Index of 15"); - deepEqual(tree.indexOf(5), 5, "Index of 5"); - deepEqual(tree.indexOf(null, callback), 6, "Index of the first even number greater than 5"); -}); - -test("RBTree - Last index of test", function () { - var tree = new RBTree(); - for (var i = 0; i < 10; i++) - tree.insert(i, i); - var callback = function (item) { - return !(item % 2) && item > 5; - }; - deepEqual(tree.lastIndexOf(0), 0, "Last index of 0"); - deepEqual(tree.lastIndexOf(15), -1, "Last index of 15"); - deepEqual(tree.lastIndexOf(5), 5, "Last index of 5"); - deepEqual(tree.lastIndexOf(null, callback), 8, "Index of the last even number greater than 5"); -}); - -test("RBTree - Indexes of test", function () { - var tree = new RBTree(); - for (var i = 0; i < 30; i++) - tree.insert(i, i % 10); - var callback = function (item) { - return !(item % 2) && item > 5; - }; - deepEqual(tree.allIndexesOf(0), [0, 10, 20], "Indexes of 0"); - deepEqual(tree.allIndexesOf(15), [], "Indexes of 15"); - deepEqual(tree.allIndexesOf(5), [5, 15, 25], "Indexes of 5"); - deepEqual(tree.allIndexesOf(null, callback), [6, 8, 16, 18, 26, 28], "Indexes of the even numbers greater than 5"); -}); - -test("RBTree - Clone test", function () { - var tree = new RBTree(); - for (var i = 0; i < 10; i++) - tree.insert(i, i); - var clone = tree.clone(); - var it = clone.getIterator(); - var j = 0; - for (it.first(); !it.isDone(); it.next(), j++) - deepEqual(it.getItem(), j, "Clone of the tree"); -}); - -test("RBTree - Clone distinct test", function () { - var tree = new RBTree(); - for (var i = 0; i < 20; i++) - tree.insert(i % 10, i % 10); - var clone = tree.cloneDistinct(); - deepEqual(clone.allIndexesOf(2), [2], "Clone of the tree"); -}); \ No newline at end of file diff --git a/Tests/RBTree_Test.ts b/Tests/RBTree_Test.ts new file mode 100644 index 0000000..7f6891a --- /dev/null +++ b/Tests/RBTree_Test.ts @@ -0,0 +1,241 @@ +/** + * Created by Stefano on 06/04/14. + */ + +QUnit.test("RBTree - Insert test", function (assert) +{ + var tree = new ds.RBTree(); + var keys = []; + for (var i = 0; i < 20; i++) + { + keys.push(Math.random()); + tree.insert(keys[i], keys[i]); + } + for (var j = 0; j < 20; j++) + assert.deepEqual(tree.search(keys[j]), keys[j], "Insert node"); + keys.sort(); + for (var k = 0; k < 20; k++) + assert.deepEqual(tree.getItem(k), keys[k], "Insert node"); +}); + +QUnit.test("RBTree - Minimum test", function (assert) +{ + var tree = new ds.RBTree(); + var keys = []; + var min = 10; + for (var i = 0; i < 20; i++) + { + keys.push(Math.random()); + tree.insert(keys[i], i); + if (keys[i] < min) + min = keys[i]; + } + assert.deepEqual(tree.minimum().item, tree.search(min), "Minimum"); +}); + +QUnit.test("RBTree - Maximum test", function (assert) +{ + var tree = new ds.RBTree(); + var keys = []; + var max = -1; + for (var i = 0; i < 20; i++) + { + keys.push(Math.random()); + tree.insert(keys[i], i); + if (keys[i] > max) + max = keys[i]; + } + assert.deepEqual(tree.maximum().item, tree.search(max), "Maximum"); +}); + +QUnit.test("RBTree - Successor test", function (assert) +{ + var tree = new ds.RBTree(); + for (var i = 0; i < 20; i++) + tree.insert(i, i); + var it = tree.getIterator(); + var j = 1; + for (it.first(); !it.isDone(); it.next(), j++) + { + var successor = tree.successor(it.getNode()); + if (successor) + assert.deepEqual(successor.item, j, "Successor"); + else + assert.deepEqual(successor, null, "No successor"); + } +}); + +QUnit.test("RBTree - Predecessor test", function (assert) +{ + var tree = new ds.RBTree(); + for (var i = 0; i < 20; i++) + tree.insert(i, i); + var it = tree.getIterator(); + var j = 18; + for (it.last(); !it.isDone(); it.previous(), j--) + { + var predecessor = tree.predecessor(it.getNode()); + if (predecessor) + assert.deepEqual(predecessor.item, j, "Predecessor"); + else + assert.deepEqual(predecessor, null, "No predecessor"); + } +}); + +QUnit.test("RBTree - Delete node test", function (assert) +{ + var tree = new ds.RBTree(); + for (var i = 0; i < 20; i++) + tree.insert(i, i); + var j = 0; + while (tree.minimum()) + { + assert.deepEqual(tree.minimum().item, j, "Deletion"); + tree.deleteNode(tree.minimum()); + j++; + } +}); + +QUnit.test("RBTree - To array test", function (assert) +{ + var tree = new ds.RBTree(); + for (var i = 0; i < 5; i++) + tree.insert(i, i); + assert.deepEqual(tree.toArray(), [0, 1, 2, 3, 4], "To array"); +}); + +QUnit.test("RBTree - Filter test", function (assert) +{ + var tree = new ds.RBTree(); + const length = 100; + + for (var i = 0; i < length; i++) + tree.insert(i, i); + + var result = tree.filter(function (item) + { + return Boolean(1 - item % 2); + }); + + assert.deepEqual(result[0], 0, "Filter of the even values"); + assert.deepEqual(result[result.length - 1], 98, "Filter on the even values"); +}); + +QUnit.test("RBTree - Clear test", function (assert) +{ + var tree = new ds.RBTreeList(); + tree.insert(0, 0); + tree.insert(2, 2); + tree.clear(); + assert.deepEqual(tree.isEmpty(), true, "Clear tree"); +}); + +QUnit.test("RBTree - Is empty test", function (assert) +{ + var tree = new ds.RBTree(); + tree.insert(0, 0); + tree.insert(2, 2); + assert.deepEqual(tree.isEmpty(), false, "Is not empty"); + tree.clear(); + assert.deepEqual(tree.isEmpty(), true, "Is empty"); +}); + +QUnit.test("RBTree - Contains test", function (assert) +{ + var tree = new ds.RBTree(); + tree.insert(0, 0); + tree.insert(2, 2); + assert.deepEqual(tree.contains(0), true, "Contains 0"); + assert.deepEqual(tree.contains(2), true, "Contains 2"); + assert.deepEqual(tree.contains(1), false, "Not contains 1"); + var callback = function (item) + { + return item > 0; + }; + assert.deepEqual(tree.fullContains(callback), true, "Contains a value > 0"); + callback = function (item) + { + return item < 0; + }; + assert.deepEqual(tree.fullContains(callback), false, "Contains a value < 0"); +}); + +QUnit.test("RBTree - Execute test", function (assert) +{ + var tree = new ds.RBTree(); + tree.insert(0, 0); + tree.insert(2, 2); + var callback = function (item) + { + return item * 2; + }; + tree.execute(callback); + assert.deepEqual(tree.search(0), 0, "Execute for key 0"); + assert.deepEqual(tree.search(2), 4, "Execute for key 1"); +}); + +QUnit.test("RBTree - Index of test", function (assert) +{ + var tree = new ds.RBTree(); + for (var i = 0; i < 10; i++) + tree.insert(i, i); + var callback = function (item) + { + return !(item % 2) && item > 5; + }; + assert.deepEqual(tree.indexOf(0), 0, "Index of 0"); + assert.deepEqual(tree.indexOf(15), -1, "Index of 15"); + assert.deepEqual(tree.indexOf(5), 5, "Index of 5"); + assert.deepEqual(tree.indexOf(null, callback), 6, "Index of the first even number greater than 5"); +}); + +QUnit.test("RBTree - Last index of test", function (assert) +{ + var tree = new ds.RBTree(); + for (var i = 0; i < 10; i++) + tree.insert(i, i); + var callback = function (item) + { + return !(item % 2) && item > 5; + }; + assert.deepEqual(tree.lastIndexOf(0), 0, "Last index of 0"); + assert.deepEqual(tree.lastIndexOf(15), -1, "Last index of 15"); + assert.deepEqual(tree.lastIndexOf(5), 5, "Last index of 5"); + assert.deepEqual(tree.lastIndexOf(null, callback), 8, "Index of the last even number greater than 5"); +}); + +QUnit.test("RBTree - Indexes of test", function (assert) +{ + var tree = new ds.RBTree(); + for (var i = 0; i < 30; i++) + tree.insert(i, i % 10); + var callback = function (item) + { + return !(item % 2) && item > 5; + }; + assert.deepEqual(tree.allIndexesOf(0), [0, 10, 20], "Indexes of 0"); + assert.deepEqual(tree.allIndexesOf(15), [], "Indexes of 15"); + assert.deepEqual(tree.allIndexesOf(5), [5, 15, 25], "Indexes of 5"); + assert.deepEqual(tree.allIndexesOf(null, callback), [6, 8, 16, 18, 26, 28], "Indexes of the even numbers greater than 5"); +}); + +QUnit.test("RBTree - Clone test", function (assert) +{ + var tree = new ds.RBTree(); + for (var i = 0; i < 10; i++) + tree.insert(i, i); + var clone = tree.clone(); + var it = clone.getIterator(); + var j = 0; + for (it.first(); !it.isDone(); it.next(), j++) + assert.deepEqual(it.getItem(), j, "Clone of the tree"); +}); + +QUnit.test("RBTree - Clone distinct test", function (assert) +{ + var tree = new ds.RBTree(); + for (var i = 0; i < 20; i++) + tree.insert(i % 10, i % 10); + var clone = tree.cloneDistinct(); + assert.deepEqual(clone.allIndexesOf(2), [2], "Clone of the tree"); +}); \ No newline at end of file diff --git a/Tests/Range_Test.js b/Tests/Range_Test.js deleted file mode 100644 index fc201ff..0000000 --- a/Tests/Range_Test.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Created by Stefano on 06/04/14. - */ - -test("Range - Create linear test", function () { - var range = Range(0, 5); - for (var j = 0; j < range.length; j++) { - deepEqual(range[j], j, "Check range values"); - } -}); - -test("Range - Create inverse test", function () { - var range = Range(5, 0, -1); - for (var j = 0; j < range.length; j++) { - deepEqual(range[j], 5 - j, "Check range values"); - } -}); - -test("Range - Create step test", function () { - var range = Range(0, 15, 4); - for (var j = 0; j < range.length; j++) { - deepEqual(range[j], j * 4, "Check range values"); - } -}); - -test("Range - Create inverse step test", function () { - var range = Range(15, 4, -2); - for (var j = 0; j < range.length; j++) { - deepEqual(range[j], 15 - j * 2, "Check range values"); - } -}); \ No newline at end of file diff --git a/Tests/Range_Test.ts b/Tests/Range_Test.ts new file mode 100644 index 0000000..6a3dbc6 --- /dev/null +++ b/Tests/Range_Test.ts @@ -0,0 +1,39 @@ +/** + * Created by Stefano on 06/04/14. + */ + +QUnit.test("Range - Create linear test", function (assert) +{ + var range = ds.Range(0, 5); + for (var j = 0; j < range.length; j++) + { + assert.deepEqual(range[j], j, "Check range values"); + } +}); + +QUnit.test("Range - Create inverse test", function (assert) +{ + var range = ds.Range(5, 0, -1); + for (var j = 0; j < range.length; j++) + { + assert.deepEqual(range[j], 5 - j, "Check range values"); + } +}); + +QUnit.test("Range - Create step test", function (assert) +{ + var range = ds.Range(0, 15, 4); + for (var j = 0; j < range.length; j++) + { + assert.deepEqual(range[j], j * 4, "Check range values"); + } +}); + +QUnit.test("Range - Create inverse step test", function (assert) +{ + var range = ds.Range(15, 4, -2); + for (var j = 0; j < range.length; j++) + { + assert.deepEqual(range[j], 15 - j * 2, "Check range values"); + } +}); \ No newline at end of file diff --git a/Tests/Set_Test.js b/Tests/Set_Test.js deleted file mode 100644 index 5720f03..0000000 --- a/Tests/Set_Test.js +++ /dev/null @@ -1,104 +0,0 @@ -/** - * Created by Stefano on 06/04/14. - */ - -test("Set - Insert test", function () { - var setA = new Set(); - var e0 = new Element(0); - var e1 = new Element(1); - setA.multiInsert([e0, e1]); - deepEqual(setA.getItems(), [0, 1], "Insert elements"); - deepEqual(setA.getCardinality(), 2, "Insert elements"); -}); - -test("Set - Union test", function () { - var setA = new Set(); - var setB = new Set(); - var e0 = new Element(0); - var e1 = new Element(1); - var e2 = new Element(2); - var e3 = new Element(3); - setA.multiInsert([e0, e1]); - setA.multiInsert([e2, e3]); - var union = setA.union(setB); - deepEqual(setA.parents.contains(union), true, "Union of sets"); - deepEqual(setB.parents.contains(union), true, "Union of sets"); - deepEqual(union.getCardinality(), 4, "Union of sets"); -}); - -test("Set - Intersection test", function () { - var setA = new Set(); - var setB = new Set(); - var e = []; - for (var i = 0; i < 6; i++) { - e.push(new Element(i)); - if (i < 4) - setA.insert(e[i]); - if (i > 1) - setB.insert(e[i]); - } - var intersection = setA.intersect(setB); - for (var k = 0; k < 2; k++) - deepEqual(intersection.elements.getItem(k).item, k + 2, "Intersection of sets"); - deepEqual(intersection.getCardinality(), 2, "Intersection of sets"); -}); - -test("Set - Difference test", function () { - var setA = new Set(); - var setB = new Set(); - var e = []; - for (var i = 0; i < 6; i++) { - e.push(new Element(i)); - if (i < 4) - setA.insert(e[i]); - if (i > 1) - setB.insert(e[i]); - } - var diffA = setA.difference(setB); - var diffB = setB.difference(setA); - for (var j = 0; j < 2; j++) - deepEqual(diffA.elements.getItem(j).item, j, "Difference of sets"); - deepEqual(diffA.getCardinality(), 2, "Difference of sets"); - for (var k = 0; k < 2; k++) - deepEqual(diffB.elements.getItem(k).item, k + 4, "Difference of sets"); - deepEqual(diffB.getCardinality(), 2, "Difference of sets"); -}); - -test("Set - Cartesian product test", function () { - var setA = new Set(); - var setB = new Set(); - var e = []; - for (var i = 0; i < 6; i++) { - e.push(new Element(i)); - if (i < 3) - setA.insert(e[i]); - if (i > 2) - setB.insert(e[i]); - } - var productA = setA.cartesianProduct(setB); - var productB = setB.cartesianProduct(setA); - deepEqual(productA.getItems(), [ - [0, 3], - [0, 4], - [0, 5], - [1, 3], - [1, 4], - [1, 5], - [2, 3], - [2, 4], - [2, 5] - ], "Cartesian product of sets"); - deepEqual(productA.getCardinality(), 9, "Cartesian product of sets"); - deepEqual(productB.getItems(), [ - [3, 0], - [3, 1], - [3, 2], - [4, 0], - [4, 1], - [4, 2], - [5, 0], - [5, 1], - [5, 2] - ], "Cartesian product of sets"); - deepEqual(productB.getCardinality(), 9, "Cartesian product of sets"); -}); \ No newline at end of file diff --git a/Tests/Set_Test.ts b/Tests/Set_Test.ts new file mode 100644 index 0000000..1316e84 --- /dev/null +++ b/Tests/Set_Test.ts @@ -0,0 +1,112 @@ +/** + * Created by Stefano on 06/04/14. + */ + +QUnit.test("Set - Insert test", function (assert) +{ + var setA = new ds.Set(); + var e0 = new ds.Element(0); + var e1 = new ds.Element(1); + setA.multiInsert([e0, e1]); + assert.deepEqual(setA.getItems(), [0, 1], "Insert elements"); + assert.deepEqual(setA.getCardinality(), 2, "Insert elements"); +}); + +QUnit.test("Set - Union test", function (assert) +{ + var setA = new ds.Set(); + var setB = new ds.Set(); + var e0 = new ds.Element(0); + var e1 = new ds.Element(1); + var e2 = new ds.Element(2); + var e3 = new ds.Element(3); + setA.multiInsert([e0, e1]); + setA.multiInsert([e2, e3]); + var union = setA.union(setB); + assert.deepEqual(setA.parents.contains(union), true, "Union of sets"); + assert.deepEqual(setB.parents.contains(union), true, "Union of sets"); + assert.deepEqual(union.getCardinality(), 4, "Union of sets"); +}); + +QUnit.test("Set - Intersection test", function (assert) +{ + var setA = new ds.Set(); + var setB = new ds.Set(); + var e = []; + for (var i = 0; i < 6; i++) + { + e.push(new ds.Element(i)); + if (i < 4) + setA.insert(e[i]); + if (i > 1) + setB.insert(e[i]); + } + var intersection = setA.intersect(setB); + for (var k = 0; k < 2; k++) + assert.deepEqual(intersection.elements.getItem(k).item, k + 2, "Intersection of sets"); + assert.deepEqual(intersection.getCardinality(), 2, "Intersection of sets"); +}); + +QUnit.test("Set - Difference test", function (assert) +{ + var setA = new ds.Set(); + var setB = new ds.Set(); + var e = []; + for (var i = 0; i < 6; i++) + { + e.push(new ds.Element(i)); + if (i < 4) + setA.insert(e[i]); + if (i > 1) + setB.insert(e[i]); + } + var diffA = setA.difference(setB); + var diffB = setB.difference(setA); + for (var j = 0; j < 2; j++) + assert.deepEqual(diffA.elements.getItem(j).item, j, "Difference of sets"); + assert.deepEqual(diffA.getCardinality(), 2, "Difference of sets"); + for (var k = 0; k < 2; k++) + assert.deepEqual(diffB.elements.getItem(k).item, k + 4, "Difference of sets"); + assert.deepEqual(diffB.getCardinality(), 2, "Difference of sets"); +}); + +QUnit.test("Set - Cartesian product test", function (assert) +{ + var setA = new ds.Set(); + var setB = new ds.Set(); + var e = []; + for (var i = 0; i < 6; i++) + { + e.push(new ds.Element(i)); + if (i < 3) + setA.insert(e[i]); + if (i > 2) + setB.insert(e[i]); + } + var productA = setA.cartesianProduct(setB); + var productB = setB.cartesianProduct(setA); + assert.deepEqual(productA.getItems(), [ + [0, 3], + [0, 4], + [0, 5], + [1, 3], + [1, 4], + [1, 5], + [2, 3], + [2, 4], + [2, 5] + ], "Cartesian product of sets"); + assert.deepEqual(productA.getCardinality(), 9, "Cartesian product of sets"); + assert.deepEqual(productB.getItems(), [ + [3, 0], + [3, 1], + [3, 2], + [4, 0], + [4, 1], + [4, 2], + [5, 0], + [5, 1], + [5, 2] + ], "Cartesian product of sets"); + assert.deepEqual(productB.getCardinality(), 9, "Cartesian product of sets"); +}); \ No newline at end of file diff --git a/Tests/Stack_Test.js b/Tests/Stack_Test.js deleted file mode 100644 index 57cae5d..0000000 --- a/Tests/Stack_Test.js +++ /dev/null @@ -1,198 +0,0 @@ -/** - * Created by Battistella Stefano on 31/03/14. - */ - -test("Stack - Init test", function () { - var stack = new Stack(0, 2, 4, 6); - deepEqual(stack.multiPop(4), [6, 4, 2, 0], "Initializing"); - stack = new Stack(0); - deepEqual(stack.multiPop(4), [0], "Initializing"); -}); - -test("Stack - Init range test", function () { - var stack = new Stack(Range(0, 6, 2)); - deepEqual(stack.multiPop(4), [6, 4, 2, 0], "Initializing"); -}); - -test("Stack - Push test", function () { - var stack = new Stack(); - stack.push(0); - deepEqual(stack.getItem(0), 0, "Push 0"); - stack.push(2); - deepEqual(stack.getItem(0), 2, "Push 2"); - deepEqual(stack.getItem(1), 0, "Push 2"); -}); - -test("Stack - Pop test", function () { - var stack = new Stack(); - stack.push(0); - stack.push(2); - deepEqual(stack.pop(), 2, "Pop"); - deepEqual(stack.pop(), 0, "Check length"); - deepEqual(stack.pop(), undefined, "Check length if too much pop"); -}); - -test("Stack - MultiPop test", function () { - var stack = new Stack(); - stack.push(0); - stack.push(2); - deepEqual(stack.multiPop(1), [2], "MultiPop 1 time"); - stack.push(4); - stack.push(5); - stack.push(8); - deepEqual(stack.multiPop(7), [8, 5, 4, 0], "MultiPop 7 times"); - deepEqual(stack.multiPop(1), [], "MultiPop 1 time with stack empty"); -}); - -test("Stack - Iterator test", function () { - var stack = new Stack(); - for (var i = 0; i < 10; i++) - stack.push(i); - var j = 9; - var it = stack.getIterator(); - for (it.first(); !it.isDone(); it.next(), j--) - deepEqual(it.getItem(), j, "Get next item " + (10 - j)); - j++; - for (it.last(); !it.isDone(); it.previous(), j++) - deepEqual(it.getItem(), j, "Get previous item " + (10 - j)); -}); - -test("Stack - Get length test", function () { - var stack = new Stack(); - deepEqual(stack.getLength(), 0, "Length 0"); - stack.push(0); - deepEqual(stack.getLength(), 1, "Length 1"); - stack.push(2); - deepEqual(stack.getLength(), 2, "Length 2"); - stack.pop(); - stack.pop(); - deepEqual(stack.getLength(), 0, "Length 0"); - -}); - -test("Stack - Peek test", function () { - var stack = new Stack(); - stack.push(0); - deepEqual(stack.peek(), 0, "Peek 0"); - stack.push(2); - deepEqual(stack.peek(), 2, "Peek 2"); -}); - -test("Stack - Clear test", function () { - var stack = new Stack(); - stack.push(0); - stack.push(2); - stack.clear(); - deepEqual(stack.isEmpty(), true, "Clear stack"); -}); - -test("Stack - Is empty test", function () { - var stack = new Stack(); - stack.push(0); - stack.push(2); - deepEqual(stack.isEmpty(), false, "Is empty"); - stack.clear(); - deepEqual(stack.isEmpty(), true, "Is empty"); -}); - -test("Stack - contains", function () { - var stack = new Stack(); - stack.push(0); - stack.push(2); - deepEqual(stack.contains(0), true, "Contains 0"); - deepEqual(stack.contains(2), true, "Contains 2"); - deepEqual(stack.contains(1), false, "Not contains 1"); - var callback = function (item) { - return item > 0; - }; - deepEqual(stack.contains(null, callback), true, "Contains a value > 0"); - callback = function (item) { - return item < 0; - }; - deepEqual(stack.contains(null, callback), false, "Contains a value < 0"); -}); - -test("Stack - execute", function () { - var stack = new Stack(); - stack.push(0); - stack.push(2); - var callback = function (item) { - return item * 2; - }; - stack.execute(callback); - deepEqual(stack.getItem(0), 4, "Execute for item 1"); - deepEqual(stack.getItem(1), 0, "Execute for item 0"); -}); - -test("Stack - Index of test", function () { - var stack = new Stack(); - for (var i = 0; i < 10; i++) - stack.push(i); - var callback = function (item) { - return !(item % 2) && item > 5; - }; - deepEqual(stack.indexOf(0), 0, "Index of 0"); - deepEqual(stack.indexOf(15), -1, "Index of 15"); - deepEqual(stack.indexOf(5), 5, "Index of 5"); - deepEqual(stack.indexOf(null, callback), 8, "Index of the first even number greater than 5"); -}); - -test("Stack - Last index of test", function () { - var stack = new Stack(); - for (var i = 0; i < 10; i++) - stack.push(i); - var callback = function (item) { - return !(item % 2) && item > 5; - }; - deepEqual(stack.lastIndexOf(0), 0, "Last index of 0"); - deepEqual(stack.lastIndexOf(15), -1, "Last index of 15"); - deepEqual(stack.lastIndexOf(5), 5, "Last index of 5"); - deepEqual(stack.lastIndexOf(null, callback), 6, "Index of the last even number greater than 5"); -}); - -test("Stack - Indexes of test", function () { - var stack = new Stack(); - for (var i = 0; i < 30; i++) - stack.push(i % 10); - var callback = function (item) { - return !(item % 2) && item > 5; - }; - deepEqual(stack.allIndexesOf(0), [20, 10, 0], "Indexes of 0"); - deepEqual(stack.allIndexesOf(15), [], "Indexes of 15"); - deepEqual(stack.allIndexesOf(5), [25, 15, 5], "Indexes of 5"); - deepEqual(stack.allIndexesOf(null, callback), [28, 26, 18, 16, 8, 6], "Indexes of the even numbers greater than 5"); -}); - -test("Stack - Clone test", function () { - var stack = new Stack(); - for (var i = 0; i < 10; i++) - stack.push(i); - var clone = stack.clone(); - var it = clone.getIterator(); - var j = 9; - for (it.first(); !it.isDone(); it.next(), j--) - deepEqual(it.getItem(), j, "Clone of the list"); -}); - -test("Stack - Clone distinct test", function () { - var stack = new Stack(); - for (var i = 0; i < 20; i++) - stack.push(i % 10); - var clone = stack.cloneDistinct(); - deepEqual(clone.allIndexesOf(2), [2], "Clone of the list"); -}); - -test("Stack - Filter test", function () { - var stack = new Stack(); - const length = 100; - - for (var i = 0; i < length; i++) - stack.push(i); - - var result = stack.filter(function (item) { - return 1 - item % 2; - }); - - deepEqual(result[0], 98, "Filter of the even values"); - deepEqual(result[result.length - 1], 0, "Filter on the even values"); -}); \ No newline at end of file diff --git a/Tests/Stack_Test.ts b/Tests/Stack_Test.ts new file mode 100644 index 0000000..8c4f946 --- /dev/null +++ b/Tests/Stack_Test.ts @@ -0,0 +1,223 @@ +/** + * Created by Battistella Stefano on 31/03/14. + */ + +QUnit.test("Stack - Init test", function (assert) +{ + var stack = new ds.Stack(0, 2, 4, 6); + assert.deepEqual(stack.multiPop(4), [6, 4, 2, 0], "Initializing"); + stack = new ds.Stack(0); + assert.deepEqual(stack.multiPop(4), [0], "Initializing"); +}); + +QUnit.test("Stack - Init range test", function (assert) +{ + var stack = new ds.Stack(ds.Range(0, 6, 2)); + assert.deepEqual(stack.multiPop(4), [6, 4, 2, 0], "Initializing"); +}); + +QUnit.test("Stack - Push test", function (assert) +{ + var stack = new ds.Stack(); + stack.push(0); + assert.deepEqual(stack.getItem(0), 0, "Push 0"); + stack.push(2); + assert.deepEqual(stack.getItem(0), 2, "Push 2"); + assert.deepEqual(stack.getItem(1), 0, "Push 2"); +}); + +QUnit.test("Stack - Pop test", function (assert) +{ + var stack = new ds.Stack(); + stack.push(0); + stack.push(2); + assert.deepEqual(stack.pop(), 2, "Pop"); + assert.deepEqual(stack.pop(), 0, "Check length"); + assert.deepEqual(stack.pop(), undefined, "Check length if too much pop"); +}); + +QUnit.test("Stack - MultiPop test", function (assert) +{ + var stack = new ds.Stack(); + stack.push(0); + stack.push(2); + assert.deepEqual(stack.multiPop(1), [2], "MultiPop 1 time"); + stack.push(4); + stack.push(5); + stack.push(8); + assert.deepEqual(stack.multiPop(7), [8, 5, 4, 0], "MultiPop 7 times"); + assert.deepEqual(stack.multiPop(1), [], "MultiPop 1 time with stack empty"); +}); + +QUnit.test("Stack - Iterator test", function (assert) +{ + var stack = new ds.Stack(); + for (var i = 0; i < 10; i++) + stack.push(i); + var j = 9; + var it = stack.getIterator(); + for (it.first(); !it.isDone(); it.next(), j--) + assert.deepEqual(it.getItem(), j, "Get next item " + (10 - j)); + j++; + for (it.last(); !it.isDone(); it.previous(), j++) + assert.deepEqual(it.getItem(), j, "Get previous item " + (10 - j)); +}); + +QUnit.test("Stack - Get length test", function (assert) +{ + var stack = new ds.Stack(); + assert.deepEqual(stack.getLength(), 0, "Length 0"); + stack.push(0); + assert.deepEqual(stack.getLength(), 1, "Length 1"); + stack.push(2); + assert.deepEqual(stack.getLength(), 2, "Length 2"); + stack.pop(); + stack.pop(); + assert.deepEqual(stack.getLength(), 0, "Length 0"); + +}); + +QUnit.test("Stack - Peek test", function (assert) +{ + var stack = new ds.Stack(); + stack.push(0); + assert.deepEqual(stack.peek(), 0, "Peek 0"); + stack.push(2); + assert.deepEqual(stack.peek(), 2, "Peek 2"); +}); + +QUnit.test("Stack - Clear test", function (assert) +{ + var stack = new ds.Stack(); + stack.push(0); + stack.push(2); + stack.clear(); + assert.deepEqual(stack.isEmpty(), true, "Clear stack"); +}); + +QUnit.test("Stack - Is empty test", function (assert) +{ + var stack = new ds.Stack(); + stack.push(0); + stack.push(2); + assert.deepEqual(stack.isEmpty(), false, "Is empty"); + stack.clear(); + assert.deepEqual(stack.isEmpty(), true, "Is empty"); +}); + +QUnit.test("Stack - contains", function (assert) +{ + var stack = new ds.Stack(); + stack.push(0); + stack.push(2); + assert.deepEqual(stack.contains(0), true, "Contains 0"); + assert.deepEqual(stack.contains(2), true, "Contains 2"); + assert.deepEqual(stack.contains(1), false, "Not contains 1"); + var callback = function (item) + { + return item > 0; + }; + assert.deepEqual(stack.contains(null, callback), true, "Contains a value > 0"); + callback = function (item) + { + return item < 0; + }; + assert.deepEqual(stack.contains(null, callback), false, "Contains a value < 0"); +}); + +QUnit.test("Stack - execute", function (assert) +{ + var stack = new ds.Stack(); + stack.push(0); + stack.push(2); + var callback = function (item) + { + return item * 2; + }; + stack.execute(callback); + assert.deepEqual(stack.getItem(0), 4, "Execute for item 1"); + assert.deepEqual(stack.getItem(1), 0, "Execute for item 0"); +}); + +QUnit.test("Stack - Index of test", function (assert) +{ + var stack = new ds.Stack(); + for (var i = 0; i < 10; i++) + stack.push(i); + var callback = function (item) + { + return !(item % 2) && item > 5; + }; + assert.deepEqual(stack.indexOf(0), 0, "Index of 0"); + assert.deepEqual(stack.indexOf(15), -1, "Index of 15"); + assert.deepEqual(stack.indexOf(5), 5, "Index of 5"); + assert.deepEqual(stack.indexOf(null, callback), 8, "Index of the first even number greater than 5"); +}); + +QUnit.test("Stack - Last index of test", function (assert) +{ + var stack = new ds.Stack(); + for (var i = 0; i < 10; i++) + stack.push(i); + var callback = function (item) + { + return !(item % 2) && item > 5; + }; + assert.deepEqual(stack.lastIndexOf(0), 0, "Last index of 0"); + assert.deepEqual(stack.lastIndexOf(15), -1, "Last index of 15"); + assert.deepEqual(stack.lastIndexOf(5), 5, "Last index of 5"); + assert.deepEqual(stack.lastIndexOf(null, callback), 6, "Index of the last even number greater than 5"); +}); + +QUnit.test("Stack - Indexes of test", function (assert) +{ + var stack = new ds.Stack(); + for (var i = 0; i < 30; i++) + stack.push(i % 10); + var callback = function (item) + { + return !(item % 2) && item > 5; + }; + assert.deepEqual(stack.allIndexesOf(0), [20, 10, 0], "Indexes of 0"); + assert.deepEqual(stack.allIndexesOf(15), [], "Indexes of 15"); + assert.deepEqual(stack.allIndexesOf(5), [25, 15, 5], "Indexes of 5"); + assert.deepEqual(stack.allIndexesOf(null, callback), [28, 26, 18, 16, 8, 6], "Indexes of the even numbers greater than 5"); +}); + +QUnit.test("Stack - Clone test", function (assert) +{ + var stack = new ds.Stack(); + for (var i = 0; i < 10; i++) + stack.push(i); + var clone = stack.clone(); + var it = clone.getIterator(); + var j = 9; + for (it.first(); !it.isDone(); it.next(), j--) + assert.deepEqual(it.getItem(), j, "Clone of the list"); +}); + +QUnit.test("Stack - Clone distinct test", function (assert) +{ + var stack = new ds.Stack(); + for (var i = 0; i < 20; i++) + stack.push(i % 10); + var clone = stack.cloneDistinct(); + assert.deepEqual(clone.allIndexesOf(2), [2], "Clone of the list"); +}); + +QUnit.test("Stack - Filter test", function (assert) +{ + var stack = new ds.Stack(); + const length = 100; + + for (var i = 0; i < length; i++) + stack.push(i); + + var result = stack.filter(function (item) + { + return Boolean(1 - item % 2); + }); + + assert.deepEqual(result[0], 98, "Filter of the even values"); + assert.deepEqual(result[result.length - 1], 0, "Filter on the even values"); +}); \ No newline at end of file diff --git a/Tests/Trie_Test.js b/Tests/Trie_Test.js deleted file mode 100644 index 5a4b894..0000000 --- a/Tests/Trie_Test.js +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Created by Stefano on 06/04/14. - */ - -test("Trie - Insert test", function () { - var trie = new Trie(); - trie.insert("Blue"); - trie.insert("Bleu"); - var strings = []; - trie.stringsToArray(strings); - deepEqual(strings, ["Bleu","Blue"], "Insert node"); - trie.insert("Abba", 0); - trie.insert("Hello", 0); - trie.insert("World", 0); - deepEqual(trie.getItem("Abba"), 0, "Insert node"); - deepEqual(trie.getItem("Hello"), 0, "Insert node"); - deepEqual(trie.getItem("World"), 0, "Insert node"); -}); - -test("Trie - Suggest test", function () { - var trie = new Trie(); - trie.insert("Blue"); - trie.insert("Boing"); - trie.insert("Yellow"); - trie.insert("Hello"); - trie.insert("He"); - trie.insert("Hola"); - deepEqual(trie.suggest(""), ["Blue","Boing", "He", "Hello", "Hola", "Yellow"], "Suggest empty string"); - deepEqual(trie.suggest("B"), ["Blue","Boing"], "Suggest B string"); - deepEqual(trie.suggest("Bo"), ["Boing"], "Suggest Bo string"); - deepEqual(trie.suggest("Ho"), ["Hola"], "Suggest Ho string"); - deepEqual(trie.suggest("A"), [], "Suggest A string"); - deepEqual(trie.suggest("Ready"), [], "Suggest Ready string"); -}); - -test("Trie - Update Item test", function () { - var trie = new Trie(); - trie.insert("Blue", 0); - trie.insert("Boing", 0); - trie.insert("Yellow", 0); - trie.insert("Hello", 0); - trie.insert("He", 0); - trie.insert("Hola", 0); - var callback = function(item) { - return item+1; - }; - var strings = trie.suggest(""); - for(var i = 0; i < strings.length; ++i) { - trie.updateItem(strings[i], callback); - deepEqual(trie.getItem(strings[i]), 1, "Value Updated"); - } -}); \ No newline at end of file diff --git a/Tests/Trie_Test.ts b/Tests/Trie_Test.ts new file mode 100644 index 0000000..6670a30 --- /dev/null +++ b/Tests/Trie_Test.ts @@ -0,0 +1,57 @@ +/** + * Created by Stefano on 06/04/14. + */ + +QUnit.test("Trie - Insert test", function (assert) +{ + var trie = new ds.Trie(); + trie.insert("Blue"); + trie.insert("Bleu"); + var strings = []; + trie.stringsToArray(strings); + assert.deepEqual(strings, ["Bleu", "Blue"], "Insert node"); + trie.insert("Abba", 0); + trie.insert("Hello", 0); + trie.insert("World", 0); + assert.deepEqual(trie.getItem("Abba"), 0, "Insert node"); + assert.deepEqual(trie.getItem("Hello"), 0, "Insert node"); + assert.deepEqual(trie.getItem("World"), 0, "Insert node"); +}); + +QUnit.test("Trie - Suggest test", function (assert) +{ + var trie = new ds.Trie(); + trie.insert("Blue"); + trie.insert("Boing"); + trie.insert("Yellow"); + trie.insert("Hello"); + trie.insert("He"); + trie.insert("Hola"); + assert.deepEqual(trie.suggest(""), ["Blue", "Boing", "He", "Hello", "Hola", "Yellow"], "Suggest empty string"); + assert.deepEqual(trie.suggest("B"), ["Blue", "Boing"], "Suggest B string"); + assert.deepEqual(trie.suggest("Bo"), ["Boing"], "Suggest Bo string"); + assert.deepEqual(trie.suggest("Ho"), ["Hola"], "Suggest Ho string"); + assert.deepEqual(trie.suggest("A"), [], "Suggest A string"); + assert.deepEqual(trie.suggest("Ready"), [], "Suggest Ready string"); +}); + +QUnit.test("Trie - Update Item test", function (assert) +{ + var trie = new ds.Trie(); + trie.insert("Blue", 0); + trie.insert("Boing", 0); + trie.insert("Yellow", 0); + trie.insert("Hello", 0); + trie.insert("He", 0); + trie.insert("Hola", 0); + var callback = function (item) + { + return item + 1; + }; + var strings = trie.suggest(""); + for (var i = 0; i < strings.length; ++i) + { + trie.updateItem(strings[i], callback); + assert.deepEqual(trie.getItem(strings[i]), 1, "Value Updated"); + } +}); \ No newline at end of file diff --git a/Tests/qunit.d.ts b/Tests/qunit.d.ts new file mode 100644 index 0000000..f348bc4 --- /dev/null +++ b/Tests/qunit.d.ts @@ -0,0 +1,600 @@ +// Type definitions for QUnit v2.0.1 +// Project: http://qunitjs.com/ +// Definitions by: James Bracy +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +interface Assert +{ + /** + * Instruct QUnit to wait for an asynchronous operation. + * + * The callback returned from `assert.async()` will throw an Error if it is + * invoked more than once (or more often than the accepted call count, if + * provided). + * + * This replaces functionality previously provided by `QUnit.stop()` and + * `QUnit.start()`. + * + * @param {number} [acceptCallCount=1] Number of expected callbacks before the test is done. + */ + async(acceptCallCount?: number): () => void; + + /** + * A deep recursive comparison, working on primitive types, arrays, objects, + * regular expressions, dates and functions. + * + * The `deepEqual()` assertion can be used just like `equal()` when comparing + * the value of objects, such that `{ key: value }` is equal to + * `{ key: value }`. For non-scalar values, identity will be disregarded by + * deepEqual. + * + * `notDeepEqual()` can be used to explicitly test deep, strict inequality. + * + * @param actual Object or Expression being tested + * @param expected Known comparision value + * @param {string} [message] A short description of the assertion + */ + deepEqual(actual: any, expected: any, message?: string): void; + + /** + * A non-strict comparison, roughly equivalent to JUnit's assertEquals. + * + * The `equal` assertion uses the simple comparison operator (`==`) to + * compare the actual and expected arguments. When they are equal, the + * assertion passes; otherwise, it fails. When it fails, both actual and + * expected values are displayed in the test result, in addition to a given + * message. + * + * `notEqual()` can be used to explicitly test inequality. + * + * `strictEqual()` can be used to test strict equality. + * + * @param actual Expression being tested + * @param expected Known comparison value + * @param {string} [message] A short description of the assertion + */ + equal(actual: any, expected: any, message?: string): void; + + /** + * Specify how many assertions are expected to run within a test. + * + * To ensure that an explicit number of assertions are run within any test, + * use `assert.expect( number )` to register an expected count. If the + * number of assertions run does not match the expected count, the test will + * fail. + * + * @param {number} amount Number of assertions in this test. + */ + expect(amount: number): void; + + /** + * An inverted deep recursive comparison, working on primitive types, + * arrays, objects, regular expressions, dates and functions. + * + * @param actual Object or Expression being tested + * @param expected Known comparison value + * @param {string} [message] A short description of the assertion + */ + notDeepEqual(actual: any, expected: any, message?: string): void; + + /** + * A non-strict comparison, checking for inequality. + * + * The `notEqual` assertion uses the simple inverted comparison operator + * (`!=`) to compare the actual and expected arguments. When they aren't + * equal, the assertion passes; otherwise, it fails. When it fails, both + * actual and expected values are displayed in the test result, in addition + * to a given message. + * + * `equal()` can be used to test equality. + * + * `notStrictEqual()` can be used to test strict inequality. + * + * @param actual Object or Expression being tested + * @param expected Known comparison value + * @param {string} [message] A short description of the assertion + */ + notEqual(actual: any, expected: any, message?: string): void; + + /** + * A boolean check, inverse of `ok()` and CommonJS's `assert.ok()`, and + * equivalent to JUnit's `assertFalse()`. Passes if the first argument is + * falsy. + * + * `notOk()` requires just one argument. If the argument evaluates to false, + * the assertion passes; otherwise, it fails. If a second message argument + * is provided, it will be displayed in place of the result. + * + * @param state Expression being tested + * @param {string} [message] A short description of the assertion + */ + notOk(state: any, message?: string): void; + + /** + * A strict comparison of an object's own properties, checking for inequality. + * + * The `notPropEqual` assertion uses the strict inverted comparison operator + * (`!==`) to compare the actual and expected arguments as Objects regarding + * only their properties but not their constructors. + * + * When they aren't equal, the assertion passes; otherwise, it fails. When + * it fails, both actual and expected values are displayed in the test + * result, in addition to a given message. + * + * `equal()` can be used to test equality. + * + * `propEqual()` can be used to test strict equality of an Object properties. + * + * @param actual Object or Expression being tested + * @param expected Known comparison value + * @param {string} [message] A short description of the assertion + */ + notPropEqual(actual: any, expected: any, message?: string): void; + + /** + * A strict comparison, checking for inequality. + * + * The `notStrictEqual` assertion uses the strict inverted comparison + * operator (`!==`) to compare the actual and expected arguments. When they + * aren't equal, the assertion passes; otherwise, it fails. When it fails, + * both actual and expected values are displayed in the test result, in + * addition to a given message. + * + * `equal()` can be used to test equality. + * + * `strictEqual()` can be used to test strict equality. + * + * @param actual Object or Expression being tested + * @param expected Known comparison value + * @param {string} [message] A short description of the assertion + */ + notStrictEqual(actual: any, expected: any, message?: string): void; + + /** + * A boolean check, equivalent to CommonJS's assert.ok() and JUnit's + * assertTrue(). Passes if the first argument is truthy. + * + * The most basic assertion in QUnit, ok() requires just one argument. If + * the argument evaluates to true, the assertion passes; otherwise, it + * fails. If a second message argument is provided, it will be displayed in + * place of the result. + * + * @param state Expression being tested + * @param {string} message A short description of the assertion + */ + ok(state: any, message?: string): void; + + /** + * A strict type and value comparison of an object's own properties. + * + * The `propEqual()` assertion provides strictly (`===`) comparison of + * Object properties. Unlike `deepEqual()`, this assertion can be used to + * compare two objects made with different constructors and prototype. + * + * `strictEqual()` can be used to test strict equality. + * + * `notPropEqual()` can be used to explicitly test strict inequality of + * Object properties. + * + * @param actual Object or Expression being tested + * @param expected Known comparison value + * @param {string} [message] A short description of the assertion + */ + propEqual(actual: any, expected: any, message?: string): void; + + /** + * Report the result of a custom assertion + * + * Some test suites may need to express an expectation that is not defined + * by any of QUnit's built-in assertions. This need may be met by + * encapsulating the expectation in a JavaScript function which returns a + * `Boolean` value representing the result; this value can then be passed + * into QUnit's `ok` assertion. + * + * A more readable solution would involve defining a custom assertion. If + * the expectation function invokes `pushResult`, QUnit will be notified of + * the result and report it accordingly. + * + * @param assertionResult The assertion result + */ + pushResult(assertResult: { + result: boolean; + actual: any; + expected: any; + message: string; + }): void; + + /** + * A strict type and value comparison. + * + * The `strictEqual()` assertion provides the most rigid comparison of type + * and value with the strict equality operator (`===`). + * + * `equal()` can be used to test non-strict equality. + * + * `notStrictEqual()` can be used to explicitly test strict inequality. + * + * @param actual Object or Expression being tested + * @param expected Known comparison value + * @param {string} [message] A short description of the assertion + */ + strictEqual(actual: any, expected: any, message?: string): void; + + /** + * Test if a callback throws an exception, and optionally compare the thrown + * error. + * + * When testing code that is expected to throw an exception based on a + * specific set of circumstances, use assert.throws() to catch the error + * object for testing and comparison. + * + * In very few environments, like Closure Compiler, throws is considered a + * reserved word and will cause an error. For that case, an alias is bundled + * called `raises`. It has the same signature and behaviour, just a + * different name. + */ + throws(block: () => void, expected?: any, message?: any): void; + raises(block: () => void, expected?: any, message?: any): void; + +} + +interface Config +{ + altertitle: boolean; + autostart: boolean; + collapse: boolean; + current: any; + filter: string | RegExp + fixture: string; + hidepassed: boolean; + maxDepth: number; + module: string; + moduleId: string[]; + notrycatch: boolean; + noglobals: boolean; + seed: string; + reorder: boolean; + requireExpects: boolean; + testId: string[]; + testTimeout: number; + scrolltop: boolean; + urlConfig: { + id?: string; + label?: string; + tooltip?: string; + value?: string | string[] | { [key: string]: string } + }[]; +} + +interface Hooks +{ + + /** + * Runs after the last test. If additional tests are defined after the + * module's queue has emptied, it will not run this hook again. + */ + after?: (assert: Assert) => void; + + /** + * Runs after each test. + */ + afterEach?: (assert: Assert) => void; + + /** + * Runs before the first test. + */ + before?: (assert: Assert) => void; + + /** + * Runs before each test. + */ + beforeEach?: (assert: Assert) => void; + +} + +interface NestedHooks +{ + /** + * Runs after the last test. If additional tests are defined after the + * module's queue has emptied, it will not run this hook again. + */ + after: (fn: (assert: Assert) => void) => void; + + /** + * Runs after each test. + */ + afterEach: (fn: (assert: Assert) => void) => void; + + /** + * Runs before the first test. + */ + before: (fn: (assert: Assert) => void) => void; + + /** + * Runs before each test. + */ + beforeEach: (fn: (assert: Assert) => void) => void; + +} + +interface QUnit +{ + + /** + * Namespace for QUnit assertions + * + * QUnit's built-in assertions are defined on the `QUnit.assert` object. An + * instance of this object is passed as the only argument to the `QUnit.test` + * function callback. + * + * This object has properties for each of QUnit's built-in assertion methods. + */ + assert: Assert; + + /** + * Register a callback to fire whenever the test suite begins. + * + * `QUnit.begin()` is called once before running any tests. + * + * @callback callback Callback to execute. + */ + begin(callback: (details: { totalTests: number }) => void): void; + + /** + * Configuration for QUnit + * + * QUnit has a bunch of internal configuration defaults, some of which are + * useful to override. Check the description for each option for details. + */ + config: Config + + /** + * Register a callback to fire whenever the test suite ends. + * + * @param callback Callback to execute + */ + done(callback: (details: { failed: number, passed: number, total: number, runtime: number }) => void): void; + + /** + * Advanced and extensible data dumping for JavaScript. + * + * This method does string serialization by parsing data structures and + * objects. It parses DOM elements to a string representation of their outer + * HTML. By default, nested structures will be displayed up to five levels + * deep. Anything beyond that is replaced by `[object Object]` and + * `[object Array]` placeholders. + * + * If you need more or less output, change the value of `QUnit.dump.maxDepth`, + * representing how deep the elements should be parsed. + * + * Note: This method used to be in QUnit.jsDump, which was changed to + * QUnit.dump. The old property will be removed in QUnit 3.0. + */ + dump: { + maxDepth: number; + parse(data: any): string + }; + + /** + * Copy the properties defined by the `mixin` object into the `target` object. + * + * This method will modify the `target` object to contain the "own" properties + * defined by the `mixin`. If the `mixin` object specifies the value of any + * attribute as undefined, this property will instead be removed from the + * `target` object. + * + * @param target An object whose properties are to be modified + * @param mixin An object describing which properties should be modified + */ + extend(target: any, mixin: any): void; + + /** + * Register a callback to fire whenever an assertion completes. + * + * This is one of several callbacks QUnit provides. Its intended for + * integration scenarios like PhantomJS or Jenkins. The properties of the + * details argument are listed below as options. + * + * @param callback Callback to execute + */ + log(callback: (details: { + result: boolean, + actual: any; + expected: any; + message: string; + source: string; + module: string; + name: string; + runtime: number; + }) => void): void; + + /** + * Group related tests under a single label. + * + * You can use the module name to organize, select, and filter tests to run. + * + * All tests inside a module callback function will be grouped into that + * module. The test names will all be preceded by the module name in the + * test results. Other modules can be nested inside this callback function, + * where their tests' names will be labeled by their names recursively + * prefixed by their parent modules. + * + * If `QUnit.module` is defined without a `nested` callback argument, all + * subsequently defined tests will be grouped into the module until another + * module is defined. + * + * Modules with test group functions allow you to define nested modules, and + * QUnit will run tests on the parent module before going deep on the nested + * ones, even if they're declared first. Additionally, any hook callbacks on + * a parent module will wrap the hooks on a nested module. In other words, + * `before` and `beforeEach` callbacks will form a queue while the + * `afterEach` and `after` callbacks will form a stack. + * + * You can specify code to run before and after tests using the hooks + * argument, and also to create properties that will be shared on the + * testing context. Any additional properties on the `hooks` object will be + * added to that context. The `hooks` argument is still optional if you call + * `QUnit.module` with a callback argument. + * + * The module's callback is invoked with the test environment as its `this` + * context, with the environment's properties copied to the module's tests, + * hooks, and nested modules. Note that changes on tests' `this` are not + * preserved between sibling tests, where `this` will be reset to the initial + * value for each test. + * + * @param {string} name Label for this group of tests + * @param hookds Callbacks to run during test execution + * @param nested A callback with grouped tests and nested modules to run under the current module label + */ + module(name: string, hooks?: Hooks, nested?: (hooks: NestedHooks) => void): void; + module(name: string, nested?: (hooks: NestedHooks) => void): void; + + /** + * Register a callback to fire whenever a module ends. + * + * @param callback Callback to execute + */ + moduleDone(callback: (details: { + name: string; + failed: number; + passed: number; + total: number; + runtime: number; + }) => void): void; + + /** + * Register a callback to fire whenever a module begins. + * + * @param callback Callback to execute + */ + moduleStart(callback: (details: { name: string }) => void): void; + + /** + * Adds a test to exclusively run, preventing all other tests from running. + * + * Use this method to focus your test suite on a specific test. QUnit.only + * will cause any other tests in your suite to be ignored. + * + * Note, that if more than one QUnit.only is present only the first instance + * will run. + * + * This is an alternative to filtering tests to run in the HTML reporter. It + * is especially useful when you use a console reporter or in a codebase + * with a large set of long running tests. + * + * @param {string} name Title of unit being tested + * @param callback Function to close over assertions + */ + only(name: string, callback: (assert: Assert) => void): void; + + /** + * DEPRECATED: Report the result of a custom assertion. + * + * This method is deprecated and it's recommended to use pushResult on its + * direct reference in the assertion context. + * + * QUnit.push reflects to the current running test, and it may leak + * assertions in asynchronous mode. Checkout assert.pushResult() to set a + * proper custom assertion. + * + * Invoking QUnit.push allows to create a readable expectation that is not + * defined by any of QUnit's built-in assertions. + * + * @deprecated + */ + push(result: boolean, actual: any, expected: any, message: string): void; + + /** + * Adds a test like object to be skipped. + * + * Use this method to replace QUnit.test() instead of commenting out entire + * tests. + * + * This test's prototype will be listed on the suite as a skipped test, + * ignoring the callback argument and the respective global and module's + * hooks. + * + * @param {string} Title of unit being tested + */ + skip(name: string, callback?: (assert: Assert) => void): void; + + /** + * Returns a single line string representing the stacktrace (call stack). + * + * This method returns a single line string representing the stacktrace from + * where it was called. According to its offset argument, `QUnit.stack()` will + * return the correspondent line from the call stack. + * + * The default `offset` is `0` and will return the current location where it + * was called. + * + * Not all browsers support retrieving stracktraces. In those, `QUnit.stack()` + * will return undefined. + * + * @param {number} offset Set the stacktrace line offset. + */ + stack(offset?: number): string; + + /** + * `QUnit.start()` must be used to start a test run that has + * `QUnit.config.autostart` set to `false`. + * + * This method was previously used to control async tests on text contexts + * along with QUnit.stop. For asynchronous tests, use assert.async instead. + * + * When your async test has multiple exit points, call `QUnit.start()` for the + * corresponding number of `QUnit.stop()` increments. + */ + start(): void; + + /** + * Add a test to run. + * + * Add a test to run using `QUnit.test()`. + * + * The `assert` argument to the callback contains all of QUnit's assertion + * methods. Use this argument to call your test assertions. + * + * `QUnit.test()` can automatically handle the asynchronous resolution of a + * Promise on your behalf if you return a thenable Promise as the result of + * your callback function. + * + * @param {string} Title of unit being tested + * @param callback Function to close over assertions + */ + test(name: string, callback: (assert: Assert) => void): void; + + /** + * Register a callback to fire whenever a test ends. + * + * @param callback Callback to execute + */ + testDone(callback: (details: { + name: string; + module: string; + failed: number; + passed: number; + total: number; + runtime: number; + }) => void): void; + + /** + * Register a callback to fire whenever a test begins. + * + * @param callback Callback to execute + */ + testStart(callback: (details: { name: string; module: string; }) => void): void; + + /** + * Are the test running from the server or not. + */ + isLocal: boolean; + + /** + * QUnit version + */ + version: string; + +} + +/* QUnit */ +declare const QUnit: QUnit; \ No newline at end of file diff --git a/Tests/tester.html b/Tests/tester.html index e79e53f..aecba8f 100644 --- a/Tests/tester.html +++ b/Tests/tester.html @@ -10,53 +10,14 @@
- - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - +