From 8753d9496d18f32afc75bedc17f95a6984081ef0 Mon Sep 17 00:00:00 2001 From: Thomas FORGIONE Date: Wed, 10 Jun 2015 17:24:07 +0200 Subject: [PATCH] Added linked list implementation --- controllers/list/index.js | 7 + controllers/list/urls.js | 3 + controllers/list/views/index.jade | 11 ++ js/List.js | 240 ++++++++++++++++++++++++++++++ js/ListTest.js | 17 +++ js/Makefile | 13 +- 6 files changed, 290 insertions(+), 1 deletion(-) create mode 100644 controllers/list/index.js create mode 100644 controllers/list/urls.js create mode 100644 controllers/list/views/index.jade create mode 100644 js/List.js create mode 100644 js/ListTest.js diff --git a/controllers/list/index.js b/controllers/list/index.js new file mode 100644 index 0000000..6ce7d1b --- /dev/null +++ b/controllers/list/index.js @@ -0,0 +1,7 @@ +module.exports.index = function(req, res) { + res.setHeader('Content-Type', 'text/html'); + + res.render('index.jade', res.locals, function(err, out) { + res.send(out); + }); +} diff --git a/controllers/list/urls.js b/controllers/list/urls.js new file mode 100644 index 0000000..7cbc258 --- /dev/null +++ b/controllers/list/urls.js @@ -0,0 +1,3 @@ +module.exports = { + '/list': 'index' +} diff --git a/controllers/list/views/index.jade b/controllers/list/views/index.jade new file mode 100644 index 0000000..99dd837 --- /dev/null +++ b/controllers/list/views/index.jade @@ -0,0 +1,11 @@ +extends ../../../views/main + +block title + title #{title} - Test + +block extrajs + script(src='/static/js/List.min.js') + script(src='/static/js/ListTest.min.js') + +block content + Hello diff --git a/js/List.js b/js/List.js new file mode 100644 index 0000000..a78124d --- /dev/null +++ b/js/List.js @@ -0,0 +1,240 @@ +var utils = (function() { + +var utils = {}; + +// Defines a double linked-list class +utils.List = function() { + this._size = 0; + this._begin = null; + this._end = null; +} + +// Returns the number of element of a list +utils.List.prototype.size = function() { + return this._size; +} + +// Pushes an element to the end of a class +utils.List.prototype.push = function(element) { + if (this._size === 0) { + this._begin = { data : element, next: null, prev: null }; + this._end = this._begin; + this._size = 1; + } else { + var newObject = { data: element, next: null, prev: this._end }; + this._end.next = newObject; + this._end = newObject; + this._size++; + } +} + +// Sort the list +utils.List.prototype.sort = function(comparator) { + + if (comparator === undefined) { + comparator = priv.defaultComparator; + } + + var array = []; + this.forEach(function(elt) { + array.push(elt); + }); + + array.sort(function(a, b) { + return comparator(a, b); + }); + + var size = this.size(); + this.clear(); + + for (var i = 0; i < size; i++) { + this.push(array[i]); + } +} + +// Remove last element and returns it +utils.List.prototype.pop = function() { + var tmp = this._end; + this._end = null; + return tmp.data; +} + +// Apply a function to each element of the list +utils.List.prototype.forEach = function(callback) { + var chain = this._begin; + + while (chain !== null) { + callback(chain.data); + chain = chain.next; + } +} + +// Apply a function to each element of the list (starting from the end) +utils.List.prototype.forEachInverse = function(callback) { + var chain = this._end; + + while (chain !== null) { + callback(chain.data); + chain = chain.prev; + } +} + +// Get ith element of the list +utils.List.prototype.at = function(ith) { + if (ith < 0 || ith >= this.size()) { + return null; + } + + var chain = this._begin; + for (var i = 0; i < ith; i++) { + chain = chain.next; + } + + return chain.data; +} + +// Clear the list +utils.List.prototype.clear = function() { + this._begin = null; + this._end = null; + this._size = 0; +} + +// Insert an element at the right place in the list +// Precondition : list must be sorted +utils.List.prototype.insertSorted = function(elt, comparator) { + if (comparator === undefined) { + comparator = priv.defaultComparator; + } + + if (this._begin === null) { + // Inserted in front (empty list) + this.push(elt); + } else if (comparator(this._begin.data, elt) > 0) { + // Inserted in front (smallest element) + var newElement = {prev: null, next: this._begin, data: elt}; + + this._begin.prev = newElement; + + this._begin = newElement; + this._size ++; + + } else if (comparator(this._end.data, elt) < 0) { + // Inserted in end + this.push(elt); + } else { + // Inserted in the middle + var chain = this._begin; + + while (chain.next !== null) { + // If chain < elt < chain.next + if (comparator(chain.next.data, elt) > 0) { + var newElement = {data: elt, next: chain.next, prev: chain}; + if (chain.next) { + chain.next.prev = newElement; + } + chain.next = newElement; + this._size ++; + return; + } + + // Next step + chain = chain.next; + } + } +} + +// Check if a list is sorted of not +utils.List.prototype.isSorted = function(comparator) { + var chain = this._begin; + + if (comparator === undefined) { + comparator = priv.defaultComparator; + } + + while (chain.next !== null) { + if (comparator(chain.data, chain.next.data) > 0) { + return false; + } + chain = chain.next; + } + + return true; +} + +// Gives an iterator to the begin of the list +utils.List.prototype.begin = function() { + return new utils.List.Iterator(this._begin, 0); +} + +// Gives an iterator to the end of the list +utils.List.prototype.end = function() { + return new utils.List.Iterator(this._end, this.size() - 1); +} + +// Class iterator +utils.List.Iterator = function(chain, counter) { + this._chain = chain; + this._counter = counter; +} + +// Go to the next element +utils.List.Iterator.prototype.next = function() { + this._chain = this._chain.next; + this._counter ++; +} + +// Go to the previous element +utils.List.Iterator.prototype.prev = function() { + this._chain = this._chain.prev; + this._counter --; +} + +// Return the current element +utils.List.Iterator.prototype.get = function() { + return this._chain.data; +} + +// Check if there is another element next +utils.List.Iterator.prototype.hasNext = function() { + return this._chain.next !== null; +} + +// Check if there is another element before +utils.List.Iterator.prototype.hasPrev = function() { + return this._chain.prev !== null; +} + +// Compares to another iterator of the same list +utils.List.Iterator.prototype.lowerThan = function(it2) { + return utils.distance(this, it2) > 0; +} + +// Compares to another iterator of the same list +utils.List.Iterator.prototype.greaterThan = function(it2) { + return utils.distance(this, it2) < 0; +} + +// Returns the distance between two iterators of the same list +utils.distance = function(it1, it2) { + return it2._counter - it1._counter; +} + +priv = {}; + +priv.defaultComparator = function(a,b) { + if (a < b) + return -1; + if (a > b) + return 1; + return 0; +} + +// Support for NodeJs +if (typeof module !== 'undefined' && module.exports) { + module.exports = utils; +} else { + return utils; +} + +})(); diff --git a/js/ListTest.js b/js/ListTest.js new file mode 100644 index 0000000..8a71b7d --- /dev/null +++ b/js/ListTest.js @@ -0,0 +1,17 @@ +var list = new utils.List(); +var size = 100; + +for (var i = 0; i < size; i++) { + list.push(Math.random()); +} + +// For with C++-style iterator +// for (var it = list.begin(); it.lowerThan(list.end()); it.next()) { +// console.log(it.get()); +// } + +console.log(false === list.isSorted()); +list.sort(); +console.log(list.isSorted()); + +console.log(size === list.size()); diff --git a/js/Makefile b/js/Makefile index 789004c..ff87c0a 100644 --- a/js/Makefile +++ b/js/Makefile @@ -6,13 +6,24 @@ else CLOSURE=./compiler.sh endif -all: Socket Three Stats ThreeTools Bouncing Multisphere StreamingSimulator PrototypeTools PrototypeReplay PrototypeInteractive Tutorial +all: List ListTest Socket Three Stats ThreeTools Bouncing Multisphere StreamingSimulator PrototypeTools PrototypeReplay PrototypeInteractive Tutorial Socket: cp socket.io/socket.io.min.js ../static/js $(CLOSURE) $(OPT) \ --js ProgressiveLoader.js >> ../static/js/socket.io.min.js +List: + $(CLOSURE) $(OPT) \ + --js List.js \ + --js_output_file ../static/js/List.min.js + +ListTest: + $(CLOSURE) $(OPT) \ + --js ListTest.js \ + --js_output_file ../static/js/ListTest.min.js + + Three: cp three/three.min.js ../static/js/ $(CLOSURE) $(OPT) \