Skip to content

Commit

Permalink
Added Linked List implementation
Browse files Browse the repository at this point in the history
TA 2016/17 JS OOP Homework
  • Loading branch information
nikolavn committed Sep 9, 2016
1 parent dfc93d9 commit 7237868
Show file tree
Hide file tree
Showing 4 changed files with 361 additions and 0 deletions.
7 changes: 7 additions & 0 deletions JS OOP/05. Class Methods and Properties/.jshintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"curly":true,
"undef":true,
"unused":true,
"esversion":6,
"strict":true
}
23 changes: 23 additions & 0 deletions JS OOP/05. Class Methods and Properties/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "task",
"version": "1.0.0",
"description": "",
"main": "task-1.js",
"directories": {
"test": "tests"
},
"scripts": {
"test": "mocha --compilers js:babel-core -R spec tests"
},
"author": "",
"license": "ISC",
"dependencies": {
"chai": "^3.5.0",
"mocha": "^3.0.2"
},
"devDependencies": {
"babel-core": "^6.14.0",
"babel-preset-es2015": "^6.14.0",
"babel-register": "^6.14.0"
}
}
171 changes: 171 additions & 0 deletions JS OOP/05. Class Methods and Properties/task/task-1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
'use strict';
class listNode {
constructor(value) {
this._value = value;
this._next = {};
}
}

class LinkedList {
constructor() {
this._head = null;
this._length = 0;
}

get first() {
return this._head._value;
}

get last() {
let current = this._head,
index = 0;
while (++index < this._length) {
current = current.next;
}
if (current.next === undefined) {
return current._value;
} else {
return null;
}
}

get length() {
return this._length;
}

*
[Symbol.iterator]() {
let current = this._head,
index = 0,
output = [];
while (++index <= this._length) {
output.push(current._value);
current = current.next;
}
yield* output;
}

append(...values) {
values.map((value) => {
let node = new listNode(value),
current;

if (this._head === null) {
this._head = node;
} else {
current = this._head;
while (current.next) {
current = current.next;
}
current.next = node;
}
this._length++;
});
return this;
}

at(...index) {
let current = this._head,
currentIndex = 0,
previous;
if (index[0] === 0) {
previous = this._head;
}
while (currentIndex++ <= index[0]) {
previous = current;
current = current.next;
}
if (index.length > 1) {
previous._value = index[1];
}

return previous._value;
}

insert(index, ...values) {
let current = this._head,
currentIndex = 0,
detachedHead;
if (index === 0) {
this.prepend(...values);
} else {
while (++currentIndex < index) {
current = current.next;
}

detachedHead = current.next;
current.next = null;
this.append(...values);
current = this._head;

while (current.next) {
current = current.next;
}
if (current.next === undefined) {

current.next = detachedHead;
}
}

return this;
}

prepend(...values) {
let previousHead = this._head,
previousLength = this._length;
this._head = null;
this._length = 0;
this.append(...values);
let current = this._head,
index = 0;
while (++index < this._length) {
current = current.next;
}
if (current.next === undefined) {
current.next = previousHead;
} else {
current = null;
}
this._length += previousLength;
return this;
}

removeAt(index) {
if (index > -1 && index < this._length) {
let current = this._head,
currentIndex = 0,
previous;
if (index === 0) {
this._head = current.next;
this._length--;
return current._value;
} else {
while (currentIndex < index) {
previous = current;
current = current.next;
currentIndex++;
}

previous.next = current.next;
this._length--;
return current._value;
}
} else {
return null;
}
}

toArray() {
let array = [];
for (let item of this) {
array.push(item);
}
return array;
}

toString() {
return this.toArray().join(' -> ');
}
}

module.exports = LinkedList;
160 changes: 160 additions & 0 deletions JS OOP/05. Class Methods and Properties/tests/tests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
'use strict';

const chai = require('chai'),
expect = chai.expect,
LinkedList = require('../task/task-1');

describe('Linked list: ', () => {
it('should have append and toString correctly', () => {

const list = new LinkedList(),
values = [1, 2, false, 3, 4];

list.append(...values);

expect(list.first).to.equal(values[0]);
expect(list.last).to.equal(values[values.length - 1]);
expect(list.length).to.equal(values.length);
expect(list.toString()).to.equal(values.join(' -> '));
});

it('append should implement chaining and toString should work correctly', () => {
const values = [1, 2, 3, 4, 5, 6],
list = new LinkedList()
.append(1, 2)
.append(3, 4)
.append(5)
.append(6);


expect(list.first).to.equal(values[0]);
expect(list.last).to.equal(values[values.length - 1]);
expect(list.length).to.equal(values.length);
expect(list.toString()).to.equal(values.join(' -> '));
});

it('should implement prepend correctly, enable chaining and toString should work correctly', () => {

const values = [0, 1, 2, 3, 4, 5],
list = new LinkedList()
.append(3, 4)
.prepend(1, 2)
.prepend(0)
.append(5);


expect(list.first).to.equal(values[0]);
expect(list.last).to.equal(values[values.length - 1]);
expect(list.length).to.equal(values.length);
expect(list.toString()).to.equal(values.join(' -> '));
});

it('should insert correctly', () => {
const values = [1, 2, 6, 7, 8],
list = new LinkedList().append(...values).insert(2, 3, 4).insert(4, 5);

expect(list.first).to.equal(1);
expect(list.length).to.equal(8);
expect(list.toString()).to.equal([1, 2, 3, 4, 5, 6, 7, 8].join(' -> '));
});

it('should insert correctly', () => {
const list = new LinkedList().append(1, 2).insert(0, 3, 4);

list.insert(list.length - 1, 'kremikovci');

expect(list.first).to.equal(3);
expect(list.last).to.equal(2);
expect(list.length).to.equal(5);
expect(list.toString()).to.equal([3, 4, 1, 'kremikovci', 2].join(' -> '));

});

it('should have correct for-of', () => {

const values = [5, 6, 38],
list = new LinkedList().append(...values);

for (const val of list) {
expect(values.indexOf(val)).to.not.equal(-1);
}
});

it('should have correct for-of', () => {

const values = [5, 6, 3, 'gosho', true, null, 'ivan', { message: 'Hello' }],
list = new LinkedList()
.append(...values.slice(4))
.prepend(...values.slice(0, 4));

for (const val of list) {
expect(val).to.equal(values.shift());
}
});

it('should have correct removeAt', () => {
const theObj = { value: 'val', message: 'hello' };
const values = ['test', true, null, 1, 2, 'testtest', theObj, 'gg'],
list = new LinkedList().append(...values),
removed1 = list.removeAt(1),
removed2 = list.removeAt(1),
removed3 = list.removeAt(0),
removed4 = list.removeAt(list.length - 1);

expect(list.first).to.equal(1);
expect(list.last).to.equal(theObj);
expect(list.length).to.equal(values.length - 4);
expect([removed1, removed2, removed3, removed4].join()).to.equal([true, null, 'test', 'gg'].join());
});

it('should have correct indexing with at(index)', () => {
const values = 'babel src --presets es2015 --out-dir ./build -s -w'.split(' '),
list = new LinkedList().append(...values),
listLength = list.length;

for (let i = 0, length = values.length; i < length; i += 1) {
expect(list.at(i)).to.equal(values[i]);
}

expect(list.first).to.equal(values[0]);
expect(list.last).to.equal(values[values.length - 1]);
expect(list.length).to.equal(listLength);
});

it('at(0) should return the same as .first', () => {
const list = new LinkedList().append(1, 2, 3, 5);

expect(list.at(0)).to.equal(list.first);
});

it('at(list.length - 1) should return the same as .last', () => {
const list = new LinkedList().append(1, 2, 3, 5);

expect(list.at(list.length - 1)).to.equal(list.last);
});

it('should have correct indexing with at(index, value)', () => {
const values = 'babel src --presets es2015 --out-dir ./build -s -w'.split(' '),
list = new LinkedList().append(...values),
listLength = list.length;

for (let i = 0, length = values.length; i < length; i += 1) {
list.at(i, i);
expect(list.at(i)).to.equal(i);
}

expect(list.first).to.equal(0);
expect(list.last).to.equal(values.length - 1);
expect(list.length).to.equal(listLength);
});

it('should have correct toArray', () => {

const values = ['test', true, null, 1, 2, 'testtest', { value: 'val', message: 'hello' }],
array = new LinkedList().append(...values).toArray();

expect(array instanceof Array).to.be.true;
expect(array.length).to.equal(values.length);
expect(JSON.stringify(array)).to.equal(JSON.stringify(values));
});
});

0 comments on commit 7237868

Please sign in to comment.