diff --git a/linked-list.js b/linked-list.js index 7973524f..c89b61c6 100644 --- a/linked-list.js +++ b/linked-list.js @@ -48,6 +48,47 @@ LinkedList.prototype.last = function() { return this.tail ? this.tail.item : undefined; }; +/** + * Method used to get the first node that contains the specified item + * + * @param {any} item - The item to locate. + * @return {Node|undefined} + */ +LinkedList.prototype.find = function(item) { + var n = this.head; + + while (n) { + if (n.item === item) { + break; + } + + n = n.next; + } + + return n || undefined; +}; + +/** + * Method used to get the last node that contains the specified item + * + * @param {any} item - The item to locate. + * @return {Node|undefined} + */ +LinkedList.prototype.findLast = function(item) { + var n = this.head, + last = null; + + while (n) { + if (n.item === item) { + last = n; + } + + n = n.next; + } + + return last || undefined; +}; + /** * Method used to add an item at the end of the list. * @@ -113,6 +154,64 @@ LinkedList.prototype.shift = function() { return node.item; }; +/** + * Method used to add the specified new item after the specified existing item + * + * @param {any} item - The item after which to add `newItem` + * @param {any} newItem - The item to be added after `item` + * @return {number} The size of the list + */ +LinkedList.prototype.addAfter = function(item, newItem) { + var node = this.find(item), + newNode, + tempNode; + + if (node === null) { + return this.size; + } + + newNode = {item: newItem, next: null}; + tempNode = node.next; + node.next = newNode; + newNode.next = tempNode; + + if (node === this.tail) { + this.tail = newNode; + } + this.size++; + + return this.size; +}; + +/** + * Method used to add the specified new item before the specified existing item + * + * @param {any} item - The item before which to add `newItem` + * @param {any} newItem - The item to be added before `item` + * @return {number} The size of the list + */ +LinkedList.prototype.addBefore = function(item, newItem) { + var parent = this.head, + newNode = {item: newItem, next: null}; + + if (parent.item === item) { + return this.unshift(newItem); + } + + while (parent.next) { + if (parent.next.item === item) { + newNode.next = parent.next; + parent.next = newNode; + this.size++; + break; + } + + parent = parent.next; + } + + return this.size; +}; + /** * Method used to iterate over the list. * diff --git a/test/linked-list.js b/test/linked-list.js index b4968930..3717ab49 100644 --- a/test/linked-list.js +++ b/test/linked-list.js @@ -70,6 +70,64 @@ describe('LinkedList', function() { assert.strictEqual(list.shift(), undefined); }); + it('should be possible to find the first node that contains a specified value', function() { + var list = new LinkedList(); + + list.push(1); + list.push(2); + list.push(3); + list.push(2); + + assert.strictEqual(list.find(1).item, list.first()); + assert.strictEqual(list.find(2).next, list.find(3)); + assert.strictEqual(list.find(5), undefined); + }); + + it('should be possible to find the last node that contains a specified value', function () { + var list = new LinkedList(); + + list.push(1); + list.push(2); + list.push(3); + list.push(2); + + assert.strictEqual(list.findLast(1).item, list.first()); + assert.strictEqual(list.findLast(2).item, list.last()); + assert.strictEqual(list.findLast(2).next, null); + assert.strictEqual(list.findLast(5), undefined); + }); + + it('should be possible to add an item after a specified item', function() { + var list = new LinkedList(); + + list.push(1); + list.push(2); + list.push(3); + + assert.strictEqual(list.addAfter(3, 4), 4); + assert.strictEqual(list.addAfter(2, 10), 5); + assert.strictEqual(list.find(2).next, list.find(10)); + assert.strictEqual(list.find(3).next, list.find(4)); + assert.strictEqual(list.last(), 4); + }); + + it('should be possible to add an item before a specified item', function() { + var list = new LinkedList(); + + list.push(1); + list.push(2); + list.push(3); + + assert.strictEqual(list.addBefore(3, 4), 4); + assert.strictEqual(list.addBefore(4, 5), 5); + assert.strictEqual(list.addBefore(1, 6), 6); + assert.strictEqual(list.addBefore(10, 5), 6); + assert.strictEqual(list.first(), 6); + assert.strictEqual(list.find(2).next, list.find(5)); + assert.strictEqual(list.find(5).next, list.find(4)); + assert.strictEqual(list.last(), 3); + }); + it('should be possible to iterate over the list.', function() { var list = new LinkedList();