From 332c2cdc4d73a7ebe8a175d2b726704b20fa78e0 Mon Sep 17 00:00:00 2001 From: Aileen Date: Mon, 8 May 2017 11:52:44 -0700 Subject: [PATCH 1/8] Setup Babel and mocha --- package.json | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index d47a351..0dc2097 100644 --- a/package.json +++ b/package.json @@ -3,16 +3,18 @@ "description": "Tests and implementations for common data structures.", "private": false, "version": "0.0.0", + "scripts": { + "build": "babel src -d lib", + "build:watch": "npm run build -- --watch", + "test": "mocha --compilers js:babel-register ./spec/*.js || true" + }, "devDependencies": { "babel-cli": "^6.18.0", + "babel-core": "^6.24.1", "babel-preset-env": "^1.1.4", "babel-register": "^6.18.0", "chai": "~1.8.0", "chai-change": "^2.1.2", "mocha": "2.0.1" - }, - "scripts": { - "build": "babel src -d lib", - "test": "mocha --compilers js:babel-register ./spec/*.js" } } From d2e366681379903265f0fc730544ffab2565385e Mon Sep 17 00:00:00 2001 From: Aileen Date: Mon, 8 May 2017 15:16:44 -0700 Subject: [PATCH 2/8] WIP test for setnext and node pass --- lib/node.js | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/stack.js | 15 ++++----------- spec/node.js | 21 +++++++++++++++++++++ src/node.js | 33 +++++++++++++++++++++++++++++++++ src/stack.js | 8 ++++---- 5 files changed, 112 insertions(+), 15 deletions(-) create mode 100644 lib/node.js create mode 100644 spec/node.js create mode 100644 src/node.js diff --git a/lib/node.js b/lib/node.js new file mode 100644 index 0000000..b6ccad1 --- /dev/null +++ b/lib/node.js @@ -0,0 +1,50 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var Node = function () { + function Node() { + _classCallCheck(this, Node); + + this.data = null; + this.next = null; + } + + _createClass(Node, [{ + key: "getData", + value: function getData(data) { + return data; + } + }, { + key: "setNext", + value: function setNext(data) { + var currentNode = new Node(); + currentNode.data = data; + this.next = currentNode; + return this; + } + }, { + key: "getNext", + value: function getNext() { + if (this.next === null) {} + return this.next; + } + }]); + + return Node; +}(); + +// const node = new Node() +// node.data = 15 +// console.log(node) +// node.setNext(14) +// console.log(node) +// console.log(node.getNext().data) + +exports.default = Node; \ No newline at end of file diff --git a/lib/stack.js b/lib/stack.js index 9de25fb..53e8470 100644 --- a/lib/stack.js +++ b/lib/stack.js @@ -1,13 +1,6 @@ -'use strict'; +// const stack = () => { -Object.defineProperty(exports, "__esModule", { - value: true -}); +// } -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var Stack = function Stack() { - _classCallCheck(this, Stack); -}; - -exports.default = Stack; \ No newline at end of file +// export default Stack +"use strict"; \ No newline at end of file diff --git a/spec/node.js b/spec/node.js new file mode 100644 index 0000000..2be2906 --- /dev/null +++ b/spec/node.js @@ -0,0 +1,21 @@ +import chai, { expect } from 'chai' +import chaiChange from 'chai-change' +import Node from '../src/node' + +chai.use(chaiChange) + +describe.only('Node', () => { + + it('is a function', () => { + const node = new Node(15) + expect(Node).to.be.a('function') + }) + + it('changes the reference to the next node and returns the original node', () => { + const node = new Node() + node.setNext(14) + expect(node.getNext().data).to.eql(14) + }) + +}) + diff --git a/src/node.js b/src/node.js new file mode 100644 index 0000000..3d94c9d --- /dev/null +++ b/src/node.js @@ -0,0 +1,33 @@ +class Node { + constructor() { + this.data = null + this.next = null + } + + getData(data) { + return data + } + + setNext(data) { + const currentNode = new Node() + currentNode.data = data + this.next = currentNode + return this + } + + getNext() { + if (this.next === null) { + } + return this.next + } + +} + +// const node = new Node() +// node.data = 15 +// console.log(node) +// node.setNext(14) +// console.log(node) +// console.log(node.getNext().data) + +export default Node \ No newline at end of file diff --git a/src/stack.js b/src/stack.js index dcd1d13..476bf25 100644 --- a/src/stack.js +++ b/src/stack.js @@ -1,5 +1,5 @@ -'use strict' +// const stack = () => { -export default class Stack { - // your code here -} +// } + +// export default Stack \ No newline at end of file From 493c5f97bbe12e7300be9bc9671fc791cd396573 Mon Sep 17 00:00:00 2001 From: Aileen Date: Mon, 8 May 2017 15:58:13 -0700 Subject: [PATCH 3/8] Complete function and test for Node --- lib/node.js | 4 ++-- spec/linked_list.js | 9 +++++++++ spec/node.js | 12 ++++++++++++ src/node.js | 4 ++-- 4 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 spec/linked_list.js diff --git a/lib/node.js b/lib/node.js index b6ccad1..317ab95 100644 --- a/lib/node.js +++ b/lib/node.js @@ -42,9 +42,9 @@ var Node = function () { // const node = new Node() // node.data = 15 -// console.log(node) +// // console.log(node) // node.setNext(14) -// console.log(node) +// // console.log(node) // console.log(node.getNext().data) exports.default = Node; \ No newline at end of file diff --git a/spec/linked_list.js b/spec/linked_list.js new file mode 100644 index 0000000..6b1666f --- /dev/null +++ b/spec/linked_list.js @@ -0,0 +1,9 @@ +import chai, { expect } from 'chai' +import chaiChange from 'chai-change' +import LinkedList from '../src/LinkedList' + +chai.use(chaiChange) + +describe.only('LinkedList', () => { + +}) \ No newline at end of file diff --git a/spec/node.js b/spec/node.js index 2be2906..4377e3d 100644 --- a/spec/node.js +++ b/spec/node.js @@ -17,5 +17,17 @@ describe.only('Node', () => { expect(node.getNext().data).to.eql(14) }) + it('returns the next node', () => { + const node = new Node() + node.setNext('Sabrin') + node.getNext() + expect(node.getNext().data).to.eql('Sabrin') + }) + + it('returns null if no next node', () => { + const node = new Node() + expect(node.getNext()).to.eql(null) + }) + }) diff --git a/src/node.js b/src/node.js index 3d94c9d..7e7e45c 100644 --- a/src/node.js +++ b/src/node.js @@ -25,9 +25,9 @@ class Node { // const node = new Node() // node.data = 15 -// console.log(node) +// // console.log(node) // node.setNext(14) -// console.log(node) +// // console.log(node) // console.log(node.getNext().data) export default Node \ No newline at end of file From db7501f0729926bc94a42d4e8b6ee77e93f8dfc6 Mon Sep 17 00:00:00 2001 From: Aileen Date: Tue, 9 May 2017 11:39:15 -0700 Subject: [PATCH 4/8] WIP LinkedList --- lib/linked_list.js | 44 ++++++++++++++++++++++++++++++++++++++ spec/linked_list.js | 34 +++++++++++++++++++++++++++++- spec/node.js | 2 +- src/linked_list.js | 51 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 lib/linked_list.js create mode 100644 src/linked_list.js diff --git a/lib/linked_list.js b/lib/linked_list.js new file mode 100644 index 0000000..61fc0e9 --- /dev/null +++ b/lib/linked_list.js @@ -0,0 +1,44 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var Node = function Node(data) { + _classCallCheck(this, Node); + + this.data = data; + this.next = null; +}; + +var LinkedList = function () { + function LinkedList() { + _classCallCheck(this, LinkedList); + + this.head = null; + this._length = 0; + } + + _createClass(LinkedList, [{ + key: "getHeadNode", + value: function getHeadNode() { + return this.head; + } + }, { + key: "getTailNode", + value: function getTailNode() {} + }, { + key: "size", + value: function size() { + return this._length; + } + }]); + + return LinkedList; +}(); + +exports.default = LinkedList; \ No newline at end of file diff --git a/spec/linked_list.js b/spec/linked_list.js index 6b1666f..8c9760b 100644 --- a/spec/linked_list.js +++ b/spec/linked_list.js @@ -1,9 +1,41 @@ import chai, { expect } from 'chai' import chaiChange from 'chai-change' -import LinkedList from '../src/LinkedList' +import LinkedList from '../src/linked_list' chai.use(chaiChange) describe.only('LinkedList', () => { + context('insert()', () => { + it('inserts the value to the list', () => { + const ll = new LinkedList() + ll.insert(10) + + expect(ll).to.eql(10) + }) + }) + + // context('getHeadNode()', () => { + // it('returns the head node in the list', () => { + // const ll = new LinkedList() + // ll.insert(10) + // ll.insert(11) + // ll.insert(12) + // ll.insert(13) + + // expect(ll.getHeadNode()).to.eql({data: 10, next: {data: 11, next: {data: 12, next: {data: 13, next: null}}}}) + // }) + // }) + + // context('getTailNode()', () => { + // it('returns the last node in the list', () => { + // const ll = new LinkedList() + // ll.insert(10) + // ll.insert(11) + // ll.insert(12) + // ll.insert(13) + + // expect(ll.getTailNode()).to.eql({data: 13, next: null}) + // }) + // }) }) \ No newline at end of file diff --git a/spec/node.js b/spec/node.js index 4377e3d..f6c9eaa 100644 --- a/spec/node.js +++ b/spec/node.js @@ -4,7 +4,7 @@ import Node from '../src/node' chai.use(chaiChange) -describe.only('Node', () => { +describe('Node', () => { it('is a function', () => { const node = new Node(15) diff --git a/src/linked_list.js b/src/linked_list.js new file mode 100644 index 0000000..3dca07a --- /dev/null +++ b/src/linked_list.js @@ -0,0 +1,51 @@ +class Node { + constructor(data) { + this.data = data + this.next = null + } +} + +class LinkedList { + constructor() { + this.head = null + this._length = 0 + } + + getHeadNode() { + return this.head + } + + getTailNode() { + let currentNode = this.head + while(currentNode.next) { + currentNode = currentNode.next + } + return currentNode + } + + insert(data) { + let node = new Node(data) + if(!this.head) { + this.head = node + } + let currentNode = this.head + while(currentNode.next) { + currentNode = currentNode.next + } + currentNode.next = node + this._length += 1 + return node + } + + size() { + return this._length + } + +} + +const ll = new LinkedList() +ll.insert(15) +console.log(ll.size()) +console.log(ll) + +// export default LinkedList \ No newline at end of file From f78cf05ce1c75a64475f2e2b6e4a535bd351d918 Mon Sep 17 00:00:00 2001 From: Aileen Date: Wed, 10 May 2017 12:42:33 -0700 Subject: [PATCH 5/8] WIP InsertBefore and InsetAfter --- lib/linked_list.js | 59 ++++++++++++++++++++++++++++++- spec/linked_list.js | 85 ++++++++++++++++++++++++++++++--------------- src/linked_list.js | 51 +++++++++++++++++++++++---- 3 files changed, 159 insertions(+), 36 deletions(-) diff --git a/lib/linked_list.js b/lib/linked_list.js index 61fc0e9..0d2f8f4 100644 --- a/lib/linked_list.js +++ b/lib/linked_list.js @@ -30,15 +30,72 @@ var LinkedList = function () { } }, { key: "getTailNode", - value: function getTailNode() {} + value: function getTailNode() { + var currentNode = this.head; + while (currentNode.next) { + currentNode = currentNode.next; + } + return currentNode.data; + } + }, { + key: "insert", + value: function insert(data) { + var node = new Node(data); + if (!this.head) { + this.head = node; + this._length += 1; + return node; + } + var currentNode = this.head; + while (currentNode.next !== null) { + currentNode = currentNode.next; + } + currentNode.next = node; + this._length += 1; + return node; + } + + // insertBefore(data, newData) { + // let currentNode = this.head + // let insertedNode + // while (currentNode !== null && insertedNode == undefined) { + // if(JSON.stringify(currentNode.next.data) === JSON.stringify(data)) + // } + + // } + }, { key: "size", value: function size() { return this._length; } + }, { + key: "isEmpty", + value: function isEmpty() { + if (!this.head) { + return true; + } + return false; + } + }, { + key: "clear", + value: function clear() { + this.head = null; + this._length = 0; + this.data = null; + } }]); return LinkedList; }(); +// const ll = new LinkedList() +// ll.insert(11) +// ll.insert(12) +// ll.insert(13) +// ll.insert(14) +// ll.clear() +// console.log(ll.getHeadNode()) + + exports.default = LinkedList; \ No newline at end of file diff --git a/spec/linked_list.js b/spec/linked_list.js index 8c9760b..33aac5a 100644 --- a/spec/linked_list.js +++ b/spec/linked_list.js @@ -4,38 +4,67 @@ import LinkedList from '../src/linked_list' chai.use(chaiChange) -describe.only('LinkedList', () => { +let ll + +describe('LinkedList', () => { + beforeEach('instantiates a new LinkedList before each test', () => { + ll = new LinkedList() + }) + context('insert()', () => { it('inserts the value to the list', () => { - const ll = new LinkedList() + expect( () => { ll.insert(15) }) + .to.alter(() => ll.size(), { from:0, to: 1}); + }) + + it('inserts a node to the tail of the list', () => { ll.insert(10) + ll.insert(11) + ll.insert(12) + ll.insert(13) + expect(ll.getTailNode()).to.eql(13) + }) + }) + + context('insertBefore()', () => { + it('inserts a node (with data "Sabrin") before the first node containing "Aileen"', + () => { + expect( () => { + ll.insert('Aileen') + ll.insert('Jas') + ll.insertBefore('Jas', 'Sabrin') + }) + .to.alter( () => ll.size(), { by: 1 }) + }) + }) - expect(ll).to.eql(10) + context('getHeadNode()', () => { + it('returns the first node in the list', () => { + ll.insert('Sabrin') + expect(ll.getHeadNode().data).to.eql('Sabrin'); }) }) - // context('getHeadNode()', () => { - // it('returns the head node in the list', () => { - // const ll = new LinkedList() - // ll.insert(10) - // ll.insert(11) - // ll.insert(12) - // ll.insert(13) - - // expect(ll.getHeadNode()).to.eql({data: 10, next: {data: 11, next: {data: 12, next: {data: 13, next: null}}}}) - // }) - // }) - - // context('getTailNode()', () => { - // it('returns the last node in the list', () => { - // const ll = new LinkedList() - // ll.insert(10) - // ll.insert(11) - // ll.insert(12) - // ll.insert(13) - - // expect(ll.getTailNode()).to.eql({data: 13, next: null}) - // }) - // }) - -}) \ No newline at end of file + context('size()', () => { + it('returns the size of the list', () => { + ll.insert('Sabrin') + expect( ll.size() ).to.eql( 1 ) + }) + }) + + context('isEmpty()', () => { + it('returns true if the list is empty', () => { + expect(ll.size()).to.eql(0) + }) + + it('returns false if the list contains a node', () => { + expect( () => { + ll.insert(15) + ll.clear() + }) + .to.alter(() => ll.size(), { by: 0}); + }) + }) + +}) + diff --git a/src/linked_list.js b/src/linked_list.js index 3dca07a..a5191d5 100644 --- a/src/linked_list.js +++ b/src/linked_list.js @@ -20,16 +20,18 @@ class LinkedList { while(currentNode.next) { currentNode = currentNode.next } - return currentNode + return currentNode.data } insert(data) { let node = new Node(data) if(!this.head) { this.head = node + this._length += 1 + return node } let currentNode = this.head - while(currentNode.next) { + while(currentNode.next !== null) { currentNode = currentNode.next } currentNode.next = node @@ -37,15 +39,50 @@ class LinkedList { return node } + // insertBefore(data, newData) { + // let currentNode = this.head + // let insertedNode + // while ( (currentNode !== null) && (insertedNode == undefined) ) { + // if(JSON.stringify(currentNode.next.data) === JSON.stringify(data)) { + // insertedNode = new Node( newData ) + // insertedNode.next = currentNode.next + // currentNode.next = insertedNode + // } + // if( (currentNode === this.head) && (currentNode.data === data) ) { + // insertedNode = new Node( newData ) + // insertedNode.next = currentNode + // this.head = insertedNode + // } + // } +// return insertedNode + // } + size() { return this._length } + isEmpty() { + if(!this.head) { + return true + } + return false + } + + clear() { + this.head = null + this._length = 0 + this.data = null + } + } -const ll = new LinkedList() -ll.insert(15) -console.log(ll.size()) -console.log(ll) +// const ll = new LinkedList() +// ll.insert(11) +// ll.insert(12) +// ll.insert(13) +// ll.insert(14) +// ll.clear() +// console.log(ll.getHeadNode()) + -// export default LinkedList \ No newline at end of file +export default LinkedList \ No newline at end of file From 87a180f8ab024a4fb25c93aae698a67b438eccac Mon Sep 17 00:00:00 2001 From: Aileen Date: Wed, 10 May 2017 21:21:21 -0700 Subject: [PATCH 6/8] WIP start remove function --- java_implementation/LinkedList.java | 48 +++++++++++++++ lib/linked_list.js | 53 +++++++++++++--- spec/linked_list.js | 52 ++++++++++++++-- src/linked_list.js | 94 +++++++++++++++++++++-------- src/stack.js | 31 +++++++++- 5 files changed, 235 insertions(+), 43 deletions(-) create mode 100644 java_implementation/LinkedList.java diff --git a/java_implementation/LinkedList.java b/java_implementation/LinkedList.java new file mode 100644 index 0000000..91140da --- /dev/null +++ b/java_implementation/LinkedList.java @@ -0,0 +1,48 @@ +package datastructures; + +public class LinkedList { + + private Node head; + private int length = 0; + + private class Node { + private final Object data; + private Node next; + + Node(Object data) { + this.data = data; + } + } + + public Object getHeadNode() { + return this.head.data; + } + + public Object getTailNode() { + Node currentNode = this.head; + while (currentNode.next != null) { + currentNode = currentNode.next; + } + return currentNode.data; + } + + public Node insert(Object data) { + Node node = new Node(data); + if (this.head == null) { + this.head = node; + this.length++; + return node; + } + Node currentNode = this.head; + while (currentNode.next != null) { + currentNode = currentNode.next; + } + currentNode.next = node; + this.length++; + return node; + } + + public int size() { + return this.length; + } +} \ No newline at end of file diff --git a/lib/linked_list.js b/lib/linked_list.js index 0d2f8f4..0f8c626 100644 --- a/lib/linked_list.js +++ b/lib/linked_list.js @@ -26,7 +26,7 @@ var LinkedList = function () { _createClass(LinkedList, [{ key: "getHeadNode", value: function getHeadNode() { - return this.head; + return this.head.data; } }, { key: "getTailNode", @@ -54,16 +54,49 @@ var LinkedList = function () { this._length += 1; return node; } + }, { + key: "insertBefore", + value: function insertBefore(data, newData) { + var currentNode = this.head; + var insertedNode = void 0; + while (currentNode !== null && insertedNode == undefined) { + if (JSON.stringify(currentNode.next.data) === JSON.stringify(data)) { + insertedNode = new Node(newData); + insertedNode.next = currentNode.next; + currentNode.next = insertedNode; + } + if (currentNode === this.head && currentNode.data === data) { + insertedNode = new Node(newData); + insertedNode.next = currentNode; + this.head = insertedNode; + } + } + this._length += 1; + return insertedNode; + } + }, { + key: "insertAfter", + value: function insertAfter(data, newData) { + var node = new Node(newData); + var currentNode = this.head; - // insertBefore(data, newData) { - // let currentNode = this.head - // let insertedNode - // while (currentNode !== null && insertedNode == undefined) { - // if(JSON.stringify(currentNode.next.data) === JSON.stringify(data)) - // } - - // } - + while (currentNode.next) { + if (currentNode.data === data) { + node.next = currentNode.next; + currentNode.next = node; + return node; + } + currentNode.next = node; + } + } + }, { + key: "removeFirst", + value: function removeFirst() { + var currentNode = this.head; + this.head = currentNode.next; + currentNode = null; + this._length--; + } }, { key: "size", value: function size() { diff --git a/spec/linked_list.js b/spec/linked_list.js index 33aac5a..7a3528f 100644 --- a/spec/linked_list.js +++ b/spec/linked_list.js @@ -27,21 +27,65 @@ describe('LinkedList', () => { }) context('insertBefore()', () => { - it('inserts a node (with data "Sabrin") before the first node containing "Aileen"', + + it('inserts a node with data Sabrin before the first node containing Aileen', () => { - expect( () => { + ll.insert('Aileen') + ll.insert('Sabrin') + expect( () => { + ll.insertBefore('Sabrin', 'Jas') + }) + .to.alter( () => ll.size(), { from: 2, to: 3}) + }) + + it('inserts a node with data Sabrin before the head node containing Aileen', () => { ll.insert('Aileen') ll.insert('Jas') ll.insertBefore('Jas', 'Sabrin') + expect(ll.getHeadNode()).to.eql('Aileen') }) - .to.alter( () => ll.size(), { by: 1 }) + }) + + + + context('insertAfter()', () => { + it('inserts a node with data Jacky after the first node containing Aileen', + () => { + expect( () => { + ll.insert('Aileen') + ll.insertAfter('Aileen', 'Jacky') + }) + .to.alter( () => ll.size(), { from: 0, to: 1}) + }) + }) + + context('remove()', () => { + it('Removes the tail node from the list', () => { + ll.insert('Sabrin') + ll.insert('James') + ll.insert('Aileen') + ll.remove() + + expect( ll.getTailNode() ).to.eql('James') + }) + }) + + context('removeFirst()', () => { + it('removes the head node from the list', () => { + ll.insert('JavaScript') + ll.insert('Java') + ll.insert('Angular') + ll.insert('React') + ll.removeFirst() + + expect( ll.getHeadNode() ).to.eql('Java') }) }) context('getHeadNode()', () => { it('returns the first node in the list', () => { ll.insert('Sabrin') - expect(ll.getHeadNode().data).to.eql('Sabrin'); + expect(ll.getHeadNode() ).to.eql('Sabrin'); }) }) diff --git a/src/linked_list.js b/src/linked_list.js index a5191d5..4843974 100644 --- a/src/linked_list.js +++ b/src/linked_list.js @@ -12,7 +12,7 @@ class LinkedList { } getHeadNode() { - return this.head + return this.head.data } getTailNode() { @@ -39,23 +39,64 @@ class LinkedList { return node } - // insertBefore(data, newData) { - // let currentNode = this.head - // let insertedNode - // while ( (currentNode !== null) && (insertedNode == undefined) ) { - // if(JSON.stringify(currentNode.next.data) === JSON.stringify(data)) { - // insertedNode = new Node( newData ) - // insertedNode.next = currentNode.next - // currentNode.next = insertedNode - // } - // if( (currentNode === this.head) && (currentNode.data === data) ) { - // insertedNode = new Node( newData ) - // insertedNode.next = currentNode - // this.head = insertedNode - // } - // } -// return insertedNode - // } + insertBefore(data, newData) { + let currentNode = this.head + let insertedNode + while ( (currentNode !== null) && (insertedNode == undefined) ) { + if(JSON.stringify(currentNode.next.data) === JSON.stringify(data)) { + insertedNode = new Node( newData ) + insertedNode.next = currentNode.next + currentNode.next = insertedNode + } + if( (currentNode === this.head) && (currentNode.data === data) ) { + insertedNode = new Node( newData ) + insertedNode.next = currentNode + this.head = insertedNode + } + } + this._length += 1 + return insertedNode + } + + insertAfter(data, newData) { + let node = new Node( newData ) + let currentNode = this.head + + while( currentNode.next ) { + if( currentNode.data === data ) { + node.next = currentNode.next + currentNode.next = node + return node + } + currentNode.next = node + } + } + + removeFirst() { + let currentNode = this.head + this.head = currentNode.next + currentNode = null + this._length -- + } + + remove(position) { + let beforeNodeToDelete = null + let nodetoDelete = null + let count + let deletedNode = null + let currentNode = this.head + let message = {Failure: 'terrible, just terrible no node in here'} + if( position < 0 || position > this._length ) { + throw new Error(message.failure) + + } + while( count < position ) { + console.log("position", position) + beforeNodeToDelete = currentNode + nodetoDelete = currentNode.next + count++ + } + } size() { return this._length @@ -76,13 +117,14 @@ class LinkedList { } -// const ll = new LinkedList() -// ll.insert(11) -// ll.insert(12) -// ll.insert(13) -// ll.insert(14) -// ll.clear() -// console.log(ll.getHeadNode()) +const ll = new LinkedList() +ll.insert(11) +ll.insert(12) +ll.insert(13) +ll.insert(14) +ll.remove(2) +console.log( ll.head.next ) + -export default LinkedList \ No newline at end of file +//export default LinkedList \ No newline at end of file diff --git a/src/stack.js b/src/stack.js index 476bf25..623c9ae 100644 --- a/src/stack.js +++ b/src/stack.js @@ -1,5 +1,30 @@ -// const stack = () => { +class Stack { + constructor() { + this.storage = "" + this._length = 0 + } -// } + push(value) { + this.storage = this.storage.concat("***", value) + this._length++ + } -// export default Stack \ No newline at end of file + pop() { + let str = this.storage.slice(this.storage.lastIndexOf('***') + 3) + this.storage = this.storage.substring(0, this.storage.lastIndexOf('***')) + this._length-- + return str + } + + size() { + return this._length + } +} + +// const stack = new Stack() +// stack.push("RedBeans") +// stack.pop() +// console.log(stack) +// console.log(stack.size()) + +export default Stack \ No newline at end of file From 5b7d3f5c65c4a0f5c70258b947ecba093d22d12f Mon Sep 17 00:00:00 2001 From: Aileen Date: Thu, 11 May 2017 12:38:22 -0700 Subject: [PATCH 7/8] WIP Work on stack and null tests for linked lists --- lib/doubly_linked_list.js | 116 ++++++++++++++++++++++++++++++++++ lib/linked_list.js | 50 ++++++++++++--- lib/stack.js | 67 ++++++++++++++++++-- spec/doubly_linked_list.js | 123 +++++++++++++++++++++++++++++++++++++ spec/linked_list.js | 19 ++++-- spec/stack.js | 23 +++++-- src/doubly_linked_list.js | 114 ++++++++++++++++++++++++++++++++++ src/linked_list.js | 51 +++++++++------ src/stack.js | 19 +++++- 9 files changed, 538 insertions(+), 44 deletions(-) create mode 100644 lib/doubly_linked_list.js create mode 100644 spec/doubly_linked_list.js create mode 100644 src/doubly_linked_list.js diff --git a/lib/doubly_linked_list.js b/lib/doubly_linked_list.js new file mode 100644 index 0000000..cff667c --- /dev/null +++ b/lib/doubly_linked_list.js @@ -0,0 +1,116 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var Node = function Node(data) { + _classCallCheck(this, Node); + + this.data = data; + this.next = null; +}; + +var DoublyLinkedList = function () { + function DoublyLinkedList() { + _classCallCheck(this, DoublyLinkedList); + + this._length = 0; + this.head = null; + this.tail = null; + } + + _createClass(DoublyLinkedList, [{ + key: 'insert', + value: function insert(value) { + var node = new Node(value); + + if (this._length) { + this.tail.next = node; + node.previous = this.tail; + this.tail = node; + } else { + this.head = node; + this.tail = node; + } + this._length++; + return node; + } + }, { + key: 'find', + value: function find(position) { + var currentNode = this.head; + var length = this._length; + var count = 1; + var message = { failure: 'Non-existent node in this list.' }; + + if (length === 0 || position < 1 || position > length) { + throw new Error(message.failure); + } + while (count < position) { + currentNode = currentNode.next; + count++; + } + return currentNode; + } + }, { + key: 'remove', + value: function remove(position) { + var currentNode = this.head; + var count = 1; + var message = { failure: 'non-existent node in this list.' }; + var beforeNodeToDelete = null; + var nodeToDelete = null; + var deletedNode = null; + + if (length === 0 || position < 1 || position > this._length) { + throw new Error(message.failure); + } + + // 2nd use-case: the first node is removed + if (position === 1) { + this.head = currentNode.next; + + // 2nd use-case: there is a second node + if (!this.head) { + this.head.previous = null; + // 2nd use-case: there is no second node + } else { + this.tail = null; + } + + // 3rd use-case: the last node is removed + } else if (position === this._length) { + this.tail = this.tail.previous; + this.tail.next = null; + // 4th use-case: a middle node is removed + } else { + while (count < position) { + currentNode = currentNode.next; + count++; + } + + beforeNodeToDelete = currentNode.previous; + nodeToDelete = currentNode; + afterNodeToDelete = currentNode.next; + + beforeNodeToDelete.next = afterNodeToDelete; + afterNodeToDelete.previous = beforeNodeToDelete; + deletedNode = nodeToDelete; + nodeToDelete = null; + } + + this._length--; + + return message.success; + } + }]); + + return DoublyLinkedList; +}(); + +exports.default = DoublyLinkedList; \ No newline at end of file diff --git a/lib/linked_list.js b/lib/linked_list.js index 0f8c626..0c143cb 100644 --- a/lib/linked_list.js +++ b/lib/linked_list.js @@ -37,6 +37,22 @@ var LinkedList = function () { } return currentNode.data; } + }, { + key: "find", + value: function find(position) { + var currentNode = this.head; + var message = { failure: "This node does not exist" }; + var count = 1; + + if (this._length === 0 || position < 1 || position > this._length) { + throw new Error(message.failure); + } + while (count < position) { + currentNode = currentNode.next; + count++; + } + return currentNode; + } }, { key: "insert", value: function insert(data) { @@ -97,6 +113,31 @@ var LinkedList = function () { currentNode = null; this._length--; } + }, { + key: "remove", + value: function remove(position) { + var currentNode = this.head; + var count = 0; + var message = { failure: 'Failure: non-existent node in this list.' }; + var beforeNodeToDelete = null; + var nodeToDelete = null; + var deletedNode = null; + + if (position < 0 || position > this._length) { + throw new Error(message.failure); + } + while (count < position) { + beforeNodeToDelete = currentNode; + nodeToDelete = currentNode.next; + count++; + } + beforeNodeToDelete.next = nodeToDelete.next; + deletedNode = nodeToDelete; + nodeToDelete = null; + this._length--; + + return deletedNode; + } }, { key: "size", value: function size() { @@ -122,13 +163,4 @@ var LinkedList = function () { return LinkedList; }(); -// const ll = new LinkedList() -// ll.insert(11) -// ll.insert(12) -// ll.insert(13) -// ll.insert(14) -// ll.clear() -// console.log(ll.getHeadNode()) - - exports.default = LinkedList; \ No newline at end of file diff --git a/lib/stack.js b/lib/stack.js index 53e8470..3eaa066 100644 --- a/lib/stack.js +++ b/lib/stack.js @@ -1,6 +1,65 @@ -// const stack = () => { +"use strict"; -// } +Object.defineProperty(exports, "__esModule", { + value: true +}); -// export default Stack -"use strict"; \ No newline at end of file +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var Stack = function () { + function Stack() { + _classCallCheck(this, Stack); + + this.storage = ""; + this._length = 0; + } + + _createClass(Stack, [{ + key: "push", + value: function push(value) { + this.storage = this.storage.concat("***", value); + this._length++; + } + }, { + key: "pop", + value: function pop() { + var str = this.storage.slice(this.storage.lastIndexOf('***') + 3); + this.storage = this.storage.substring(0, this.storage.lastIndexOf('***')); + this._length--; + return str; + } + }, { + key: "size", + value: function size() { + return this._length; + } + + // peek() { + // return this.storage.charAt(3) + // } + + }, { + key: "isEmpty", + value: function isEmpty() { + if (this._length == 0) { + return true; + } + return false; + } + }, { + key: "length", + value: function length() { + return this._length; + } + }]); + + return Stack; +}(); + +// const stack = new Stack() +// stack.push("RedBeans") +// console.log(stack.length()) + +exports.default = Stack; \ No newline at end of file diff --git a/spec/doubly_linked_list.js b/spec/doubly_linked_list.js new file mode 100644 index 0000000..ce76a38 --- /dev/null +++ b/spec/doubly_linked_list.js @@ -0,0 +1,123 @@ +import chai, { expect } from 'chai' +import chaiChange from 'chai-change' +import DoublyLinkedList from '../src/linked_list' + +chai.use(chaiChange) + +let dl + +describe('DoublyLinkedList', () => { + beforeEach('instantiates a new DoublyLinkedList before each test', () => { + dl = new DoublyLinkedList() + }) + + context('insert()', () => { + it('inserts the value to the list', () => { + expect( () => { dl.insert(15) }) + .to.alter(() => dl.size(), { from:0, to: 1}); + }) + + // it('inserts a node to the tail of the list', () => { + // dl.insert(10) + // dl.insert(11) + // dl.insert(12) + // dl.insert(13) + // expect(dl.getTailNode()).to.eql(13) + // }) + }) + + // context('insertBefore()', () => { + + // it('inserts a node with data Sabrin before the first node containing Aileen', + // () => { + // dl.insert('Aileen') + // dl.insert('Sabrin') + // expect( () => { + // dl.insertBefore('Sabrin', 'Jas') + // }) + // .to.alter( () => dl.size(), { from: 2, to: 3}) + // }) + + // it('inserts a node with data Sabrin before the head node containing Aileen', () => { + // dl.insert('Aileen') + // dl.insert('Jas') + // dl.insertBefore('Jas', 'Sabrin') + // expect(dl.getHeadNode()).to.eql('Aileen') + // }) + // }) + + // context('insertAfter()', () => { + // it('inserts a node with data Jacky after the first node containing Aileen', + // () => { + // expect( () => { + // dl.insert('Aileen') + // dl.insertAfter('Aileen', 'Jacky') + // }) + // .to.alter( () => dl.size(), { from: 0, to: 1}) + // }) + // }) + + context('remove(position)', () => { + it('Removes the node from a position in the list', () => { + dl.insert('Sabrin') + dl.insert('James') + dl.insert('Aileen') + dl.remove(2) + + expect( dl.head.next.data ).to.eql('Aileen') + }) + }) + + // context('removeFirst()', () => { + // it('removes the head node from the list', () => { + // dl.insert('JavaScript') + // dl.insert('Java') + // dl.insert('Angular') + // dl.insert('React') + // dl.removeFirst() + + // expect( dl.getHeadNode() ).to.eql('Java') + // }) + // }) + + context('getHeadNode()', () => { + it('returns the first node in the list', () => { + dl.insert('Sabrin') + expect(dl.getHeadNode() ).to.eql('Sabrin'); + }) + }) + + context('size()', () => { + it('returns the size of the list', () => { + dl.insert('Sabrin') + expect( dl.size() ).to.eql( 1 ) + }) + }) + + context('isEmpty()', () => { + it('returns true if the list is empty', () => { + expect(dl.size()).to.eql(0) + }) + + it('returns false if the list contains a node', () => { + expect( () => { + dl.insert(15) + dl.clear() + }) + .to.alter(() => dl.size(), { by: 0}); + }) + }) + + context('find(position)', () => { + it('returns the first node containing the provided data', () => { + dl.insert('Sabrin') + dl.insert('Aileen') + dl.insert('Jas') + dl.insert('Mishi') + + expect(dl.find(3).data).to.eql('Jas') + }) + }) + +}) + diff --git a/spec/linked_list.js b/spec/linked_list.js index 7a3528f..e3e5e4a 100644 --- a/spec/linked_list.js +++ b/spec/linked_list.js @@ -59,14 +59,14 @@ describe('LinkedList', () => { }) }) - context('remove()', () => { - it('Removes the tail node from the list', () => { + context('remove(position)', () => { + it('Removes the node from a position in the list', () => { ll.insert('Sabrin') ll.insert('James') ll.insert('Aileen') - ll.remove() + ll.remove(2) - expect( ll.getTailNode() ).to.eql('James') + expect( ll.head.next.data ).to.eql('Aileen') }) }) @@ -110,5 +110,16 @@ describe('LinkedList', () => { }) }) + context('find(position)', () => { + it('returns the first node containing the provided data', () => { + ll.insert('Sabrin') + ll.insert('Aileen') + ll.insert('Jas') + ll.insert('Mishi') + + expect(ll.find(3).data).to.eql('Jas') + }) + }) + }) diff --git a/spec/stack.js b/spec/stack.js index 743122a..ff7399b 100644 --- a/spec/stack.js +++ b/spec/stack.js @@ -4,8 +4,12 @@ import Stack from '../src/stack' chai.use(chaiChange) +let stack + describe('Stack', () => { - 'use strict' + beforeEach('instantiates a new Stack before each test', () => { + stack = new Stack() + }) it('exists', () => { expect(Stack).to.be.a('function') @@ -13,10 +17,21 @@ describe('Stack', () => { context('push()', () => { it('pushes an element to the top of the stack.', () => { - const myStack = new Stack() - expect(() => myStack.push('foo')) - .to.alter(() => myStack.length(), { from: 0, to: 1 }) + expect(() => stack.push('Java')) + .to.alter(() => stack.size(), { from: 0, to: 1 }) }) }) + + context('pop()', () => { + it('returns and removes the top element in the stack', () => { + stack.push('Python') + stack.push('Ruby') + stack.push('Rails') + stack.push('JavaScript') + + expect(stack.pop()).to.eql('JavaScript') + }) + }) + }) diff --git a/src/doubly_linked_list.js b/src/doubly_linked_list.js new file mode 100644 index 0000000..bd6a072 --- /dev/null +++ b/src/doubly_linked_list.js @@ -0,0 +1,114 @@ +class Node { + constructor(data) { + this.data = data + this.next = null + } +} + +class DoublyLinkedList { + constructor() { + this._length = 0 + this.head = null + this.tail = null + } + + getHeadNode() { + return this.head + } + + getTailNode() { + return this.tail + } + + insert(value) { + var node = new Node(value); + + if (this._length) { + this.tail.next = node + node.previous = this.tail + this.tail = node + } else { + this.head = node + this.tail = node + } + this._length++ + return node + } + + find(position) { + let currentNode = this.head + let length = this._length + let count = 1 + let message = {failure: 'Non-existent node in this list.'} + + if (length === 0 || position < 1 || position > length) { + throw new Error(message.failure) + } + while (count < position) { + currentNode = currentNode.next + count++ + } + return currentNode + } + + remove(position) { + let currentNode = this.head + let count = 1 + let message = {failure: 'non-existent node in this list.'} + let beforeNodeToDelete = null + let nodeToDelete = null + let deletedNode = null + + if (length === 0 || position < 1 || position > this._length) { + throw new Error(message.failure) + } + if (!this.head) { + this.head.previous = null + } else { + this.tail = null + } else if (position === this._length) { + this.tail = this.tail.previous; + this.tail.next = null; + } else { + while (count < position) { + currentNode = currentNode.next; + count++; + } + beforeNodeToDelete = currentNode.previous; + nodeToDelete = currentNode; + afterNodeToDelete = currentNode.next; + + beforeNodeToDelete.next = afterNodeToDelete; + afterNodeToDelete.previous = beforeNodeToDelete; + deletedNode = nodeToDelete; + nodeToDelete = null; + } + this._length--; + return message.success; + } + + // removeFirst(position) { + // if (position === 1) { + // this.head = currentNode.next; + // } + + isEmpty() { + if(!this.head) { + return true + } + return false + } + + clear() { + this._length = 0 + this.head = null + this.tail = null + } + + size() { + return this._length + } + +} + +export default DoublyLinkedList diff --git a/src/linked_list.js b/src/linked_list.js index 4843974..75c6867 100644 --- a/src/linked_list.js +++ b/src/linked_list.js @@ -23,6 +23,21 @@ class LinkedList { return currentNode.data } + find(position) { + let currentNode = this.head + let message = {failure: "This node does not exist"} + let count = 1 + + if (this._length === 0 || position < 1 || position > this._length) { + throw new Error(message.failure); + } + while (count < position) { + currentNode = currentNode.next; + count++; + } + return currentNode; + } + insert(data) { let node = new Node(data) if(!this.head) { @@ -76,26 +91,32 @@ class LinkedList { let currentNode = this.head this.head = currentNode.next currentNode = null - this._length -- + this._length-- } remove(position) { + let currentNode = this.head + let count = 0 + let message = {failure: 'Failure: non-existent node in this list.'} let beforeNodeToDelete = null - let nodetoDelete = null - let count + let nodeToDelete = null let deletedNode = null - let currentNode = this.head - let message = {Failure: 'terrible, just terrible no node in here'} + if( position < 0 || position > this._length ) { throw new Error(message.failure) } - while( count < position ) { - console.log("position", position) + while (count < position) { beforeNodeToDelete = currentNode - nodetoDelete = currentNode.next + nodeToDelete = currentNode.next count++ - } + } + beforeNodeToDelete.next = nodeToDelete.next + deletedNode = nodeToDelete + nodeToDelete = null + this._length-- + + return deletedNode } size() { @@ -117,14 +138,4 @@ class LinkedList { } -const ll = new LinkedList() -ll.insert(11) -ll.insert(12) -ll.insert(13) -ll.insert(14) -ll.remove(2) -console.log( ll.head.next ) - - - -//export default LinkedList \ No newline at end of file +export default LinkedList \ No newline at end of file diff --git a/src/stack.js b/src/stack.js index 623c9ae..715589a 100644 --- a/src/stack.js +++ b/src/stack.js @@ -19,12 +19,25 @@ class Stack { size() { return this._length } + + // peek() { + // return this.storage.charAt(3) + // } + + isEmpty() { + if (this._length == 0) { + return true + } + return false + } + + length() { + return this._length + } } // const stack = new Stack() // stack.push("RedBeans") -// stack.pop() -// console.log(stack) -// console.log(stack.size()) +// console.log(stack.length()) export default Stack \ No newline at end of file From 0825ecb4282cdb0ff6da065a4a947f5d21f6571c Mon Sep 17 00:00:00 2001 From: Aileen Date: Thu, 11 May 2017 20:11:34 -0700 Subject: [PATCH 8/8] Complete Queue class and specs --- lib/doubly_linked_list.js | 61 +++++++++++++++++-------- lib/priority_queue.js | 1 + lib/queue.js | 75 ++++++++++++++++++++++++++++++ lib/stack.js | 47 +++++++------------ spec/queue.js | 96 +++++++++++++++++++++++++++++++++++++++ src/doubly_linked_list.js | 43 +++++++++--------- src/queue.js | 55 ++++++++++++++++++++++ src/stack.js | 40 ++++++---------- 8 files changed, 319 insertions(+), 99 deletions(-) create mode 100644 lib/priority_queue.js create mode 100644 lib/queue.js create mode 100644 spec/queue.js create mode 100644 src/queue.js diff --git a/lib/doubly_linked_list.js b/lib/doubly_linked_list.js index cff667c..192527c 100644 --- a/lib/doubly_linked_list.js +++ b/lib/doubly_linked_list.js @@ -25,6 +25,16 @@ var DoublyLinkedList = function () { } _createClass(DoublyLinkedList, [{ + key: 'getHeadNode', + value: function getHeadNode() { + return this.head; + } + }, { + key: 'getTailNode', + value: function getTailNode() { + return this.tail; + } + }, { key: 'insert', value: function insert(value) { var node = new Node(value); @@ -61,39 +71,26 @@ var DoublyLinkedList = function () { key: 'remove', value: function remove(position) { var currentNode = this.head; + var length = this._length; var count = 1; - var message = { failure: 'non-existent node in this list.' }; + var message = { failure: 'Failure: non-existent node in this list.' }; var beforeNodeToDelete = null; var nodeToDelete = null; var deletedNode = null; - if (length === 0 || position < 1 || position > this._length) { + // 1st use-case: an invalid position + if (length === 0 || position < 1 || position > length) { throw new Error(message.failure); } - // 2nd use-case: the first node is removed - if (position === 1) { - this.head = currentNode.next; - - // 2nd use-case: there is a second node - if (!this.head) { - this.head.previous = null; - // 2nd use-case: there is no second node - } else { - this.tail = null; - } - - // 3rd use-case: the last node is removed - } else if (position === this._length) { + if (position === this._length) { this.tail = this.tail.previous; this.tail.next = null; - // 4th use-case: a middle node is removed } else { while (count < position) { currentNode = currentNode.next; count++; } - beforeNodeToDelete = currentNode.previous; nodeToDelete = currentNode; afterNodeToDelete = currentNode.next; @@ -103,11 +100,35 @@ var DoublyLinkedList = function () { deletedNode = nodeToDelete; nodeToDelete = null; } - this._length--; - return message.success; } + + // removeFirst(position) { + // if (position === 1) { + // this.head = currentNode.next; + // } + + }, { + key: 'isEmpty', + value: function isEmpty() { + if (!this.head) { + return true; + } + return false; + } + }, { + key: 'clear', + value: function clear() { + this._length = 0; + this.head = null; + this.tail = null; + } + }, { + key: 'size', + value: function size() { + return this._length; + } }]); return DoublyLinkedList; diff --git a/lib/priority_queue.js b/lib/priority_queue.js new file mode 100644 index 0000000..9a390c3 --- /dev/null +++ b/lib/priority_queue.js @@ -0,0 +1 @@ +"use strict"; \ No newline at end of file diff --git a/lib/queue.js b/lib/queue.js new file mode 100644 index 0000000..8d3409d --- /dev/null +++ b/lib/queue.js @@ -0,0 +1,75 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var Queue = function () { + function Queue(capacity) { + _classCallCheck(this, Queue); + + this._capacity = capacity || Infinity; + this._storage = {}; + this._head = 0; + this._tail = 0; + } + + _createClass(Queue, [{ + key: 'enqueue', + value: function enqueue(value) { + if (this.length() < this._capacity) { + this._storage[this._tail++] = value; + return this.length(); + } + return 'Max capacity reached. Remove element before adding one'; + } + }, { + key: 'dequeue', + value: function dequeue() { + if (this.isEmpty()) { + return null; + } + var element = this._storage[this._head]; + delete this._storage[this._head]; + if (this._head < this._tail) this._head++; + return element; + } + }, { + key: 'length', + value: function length() { + return this._tail - this._head; + } + }, { + key: 'front', + value: function front() { + if (this.isEmpty()) { + return null; + } + return this._storage[0]; + } + }, { + key: 'back', + value: function back() { + if (this.isEmpty()) { + return null; + } + return this._storage[Object.keys(this._storage)[Object.keys(this._storage).length - 1]]; + } + }, { + key: 'isEmpty', + value: function isEmpty() { + for (var prop in this._storage) { + if (this._storage.hasOwnProperty(prop)) return false; + } + return true; + } + }]); + + return Queue; +}(); + +exports.default = Queue; \ No newline at end of file diff --git a/lib/stack.js b/lib/stack.js index 3eaa066..fb81a05 100644 --- a/lib/stack.js +++ b/lib/stack.js @@ -12,54 +12,39 @@ var Stack = function () { function Stack() { _classCallCheck(this, Stack); - this.storage = ""; - this._length = 0; + this.storage = {}; + this._count = 0; } _createClass(Stack, [{ key: "push", value: function push(value) { - this.storage = this.storage.concat("***", value); - this._length++; + this.storage[this._count] = value; + this._count++; } }, { key: "pop", value: function pop() { - var str = this.storage.slice(this.storage.lastIndexOf('***') + 3); - this.storage = this.storage.substring(0, this.storage.lastIndexOf('***')); - this._length--; - return str; + var value = this.storage[--this._count]; + delete this.storage[this._count]; + if (this._count < 0) { + this._count = 0; + } + return value; } }, { - key: "size", - value: function size() { - return this._length; + key: "peek", + value: function peek() { + return this.storage[this._count - 1]; } - - // peek() { - // return this.storage.charAt(3) - // } - }, { - key: "isEmpty", - value: function isEmpty() { - if (this._length == 0) { - return true; - } - return false; - } - }, { - key: "length", - value: function length() { - return this._length; + key: "size", + value: function size() { + return this._count; } }]); return Stack; }(); -// const stack = new Stack() -// stack.push("RedBeans") -// console.log(stack.length()) - exports.default = Stack; \ No newline at end of file diff --git a/spec/queue.js b/spec/queue.js new file mode 100644 index 0000000..d8a5990 --- /dev/null +++ b/spec/queue.js @@ -0,0 +1,96 @@ +import chai, { expect } from 'chai' +import chaiChange from 'chai-change' +import Queue from '../src/queue' + +chai.use(chaiChange) + +let queue + +describe('Queue', () => { + beforeEach('instantiates a new Queue before each test', () => { + queue = new Queue() + }) + + it('exists', () => { + expect(Queue).to.be.a('function') + }) + + context('enqueue(value)', () => { + it('adds an element to the back of the queue', () => { + queue.enqueue('Jas') + queue.enqueue('Aileen') + + expect(queue.enqueue('Sabrin')).to.eql(3) + }) + }) + + context('dequeue()', () => { + it('returns and removes the front element in the queue', () => { + queue.enqueue('Sabrin') + queue.enqueue('Jas') + queue.enqueue('Aileen') + queue.dequeue('Sabrin') + + expect(queue._storage).to.eql({ '1': 'Jas', '2': 'Aileen' }) + }) + + it('returns null if there is nothing in the queue', () => { + + expect(queue.dequeue()).to.eql(null) + }) + }) + + context('front()', () => { + it('returns the front element in queue', () => { + queue.enqueue('Jas') + queue.enqueue('Aileen') + + expect(queue.front()).to.eql('Jas') + }) + + it('returns null if there is nothing in the queue', () => { + + expect(queue.front()).to.eql(null) + }) + }) + + context('isEmpty()', () => { + it('returns the true if the queue is empty', () => { + + expect(queue.isEmpty()).to.eql(true) + }) + + it('returns false if there is something in the queue', () => { + queue.enqueue('Jas') + queue.enqueue('Aileen') + + expect(queue.isEmpty()).to.eql(false) + }) + }) + + context('back()', () => { + it('returns the back element in the queue', () => { + queue.enqueue('Jas') + queue.enqueue('Aileen') + queue.enqueue('Sabrin') + + expect(queue.back()).to.eql('Sabrin') + }) + + it('returns null if the queue is empty', () => { + + expect(queue.back()).to.eql(null) + }) + }) + + context('length()', () => { + it('returns the number of elements in the queue', () => { + queue.enqueue('Jas') + queue.enqueue('Aileen') + queue.enqueue('Sabrin') + + expect(queue.length()).to.eql(3) + }) + }) + +}) \ No newline at end of file diff --git a/src/doubly_linked_list.js b/src/doubly_linked_list.js index bd6a072..8b62126 100644 --- a/src/doubly_linked_list.js +++ b/src/doubly_linked_list.js @@ -53,38 +53,37 @@ class DoublyLinkedList { remove(position) { let currentNode = this.head + let length = this._length let count = 1 - let message = {failure: 'non-existent node in this list.'} + let message = {failure: 'Failure: non-existent node in this list.'} let beforeNodeToDelete = null let nodeToDelete = null let deletedNode = null - if (length === 0 || position < 1 || position > this._length) { - throw new Error(message.failure) + // 1st use-case: an invalid position + if (length === 0 || position < 1 || position > length) { + throw new Error(message.failure) } - if (!this.head) { - this.head.previous = null - } else { - this.tail = null - } else if (position === this._length) { - this.tail = this.tail.previous; - this.tail.next = null; + + if (position === this._length) { + this.tail = this.tail.previous + this.tail.next = null } else { while (count < position) { - currentNode = currentNode.next; - count++; + currentNode = currentNode.next + count++ } - beforeNodeToDelete = currentNode.previous; - nodeToDelete = currentNode; - afterNodeToDelete = currentNode.next; - - beforeNodeToDelete.next = afterNodeToDelete; - afterNodeToDelete.previous = beforeNodeToDelete; - deletedNode = nodeToDelete; - nodeToDelete = null; + beforeNodeToDelete = currentNode.previous + nodeToDelete = currentNode + afterNodeToDelete = currentNode.next + + beforeNodeToDelete.next = afterNodeToDelete + afterNodeToDelete.previous = beforeNodeToDelete + deletedNode = nodeToDelete + nodeToDelete = null } - this._length--; - return message.success; + this._length-- + return message.success } // removeFirst(position) { diff --git a/src/queue.js b/src/queue.js new file mode 100644 index 0000000..eb7aa8a --- /dev/null +++ b/src/queue.js @@ -0,0 +1,55 @@ +class Queue { + constructor(capacity) { + this._capacity = capacity || Infinity + this._storage = {} + this._head = 0 + this._tail = 0 + } + + enqueue(value) { + if (this.length() < this._capacity) { + this._storage[this._tail++] = value + return this.length() + } + return 'Max capacity reached. Remove element before adding one' + } + + dequeue() { + if (this.isEmpty()) { + return null + } + let element = this._storage[this._head] + delete this._storage[this._head] + if (this._head < this._tail) this._head++ + return element + } + + length() { + return this._tail - this._head + } + + front() { + if (this.isEmpty()) { + return null + } + return this._storage[0] + } + + back() { + if (this.isEmpty()) { + return null + } + return this._storage[Object.keys(this._storage)[Object.keys(this._storage).length - 1]] + } + + isEmpty() { + for(var prop in this._storage) { + if(this._storage.hasOwnProperty(prop)) + return false; + } + return true; + } + +} + +export default Queue \ No newline at end of file diff --git a/src/stack.js b/src/stack.js index 715589a..b22b255 100644 --- a/src/stack.js +++ b/src/stack.js @@ -1,43 +1,31 @@ class Stack { constructor() { - this.storage = "" - this._length = 0 + this.storage = {} + this._count = 0; } push(value) { - this.storage = this.storage.concat("***", value) - this._length++ + this.storage[this._count] = value + this._count++ } pop() { - let str = this.storage.slice(this.storage.lastIndexOf('***') + 3) - this.storage = this.storage.substring(0, this.storage.lastIndexOf('***')) - this._length-- - return str + let value = this.storage[--this._count] + delete this.storage[this._count] + if (this._count < 0) { + this._count = 0 + } + return value } - size() { - return this._length + peek() { + return this.storage[this._count-1] } - // peek() { - // return this.storage.charAt(3) - // } - - isEmpty() { - if (this._length == 0) { - return true - } - return false + size() { + return this._count } - length() { - return this._length - } } -// const stack = new Stack() -// stack.push("RedBeans") -// console.log(stack.length()) - export default Stack \ No newline at end of file