Skip to content

Commit 8c46dbf

Browse files
committedApr 9, 2018
Make it possible to add objects to LinkedList.
1 parent cdf7220 commit 8c46dbf

File tree

10 files changed

+204
-189
lines changed

10 files changed

+204
-189
lines changed
 

‎src/data-structures/hash-table/HashTable.js

+19-3
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,32 @@ export default class HashTable {
2121

2222
insert(key, value) {
2323
const bucketLinkedList = this.buckets[this.hash(key)];
24-
bucketLinkedList.appendUnique({ key, value });
24+
const node = bucketLinkedList.find({ callback: nodeValue => nodeValue.key === key });
25+
26+
if (!node) {
27+
// Insert new node.
28+
bucketLinkedList.append({ key, value });
29+
} else {
30+
// Update value of existing node.
31+
node.value.value = value;
32+
}
2533
}
2634

2735
delete(key) {
2836
const bucketLinkedList = this.buckets[this.hash(key)];
29-
return bucketLinkedList.deleteByKey(key);
37+
const node = bucketLinkedList.find({ callback: nodeValue => nodeValue.key === key });
38+
39+
if (node) {
40+
return bucketLinkedList.delete(node.value);
41+
}
42+
43+
return null;
3044
}
3145

3246
get(key) {
3347
const bucketLinkedList = this.buckets[this.hash(key)];
34-
return bucketLinkedList.findByKey(key);
48+
const node = bucketLinkedList.find({ callback: nodeValue => nodeValue.key === key });
49+
50+
return node ? node.value.value : null;
3551
}
3652
}

‎src/data-structures/hash-table/__test__/HashTable.test.js

+22-7
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,34 @@ describe('HashTable', () => {
3131
hashTable.insert('c', 'earth');
3232
hashTable.insert('d', 'ocean');
3333

34-
expect(hashTable.buckets[0].toString()).toBe('c:earth');
35-
expect(hashTable.buckets[1].toString()).toBe('a:sky,d:ocean');
36-
expect(hashTable.buckets[2].toString()).toBe('b:sea');
34+
const stringifier = value => `${value.key}:${value.value}`;
3735

38-
expect(hashTable.get('a').value).toBe('sky');
39-
expect(hashTable.get('d').value).toBe('ocean');
36+
expect(hashTable.buckets[0].toString(stringifier)).toBe('c:earth');
37+
expect(hashTable.buckets[1].toString(stringifier)).toBe('a:sky,d:ocean');
38+
expect(hashTable.buckets[2].toString(stringifier)).toBe('b:sea');
39+
40+
expect(hashTable.get('a')).toBe('sky');
41+
expect(hashTable.get('d')).toBe('ocean');
4042

4143
hashTable.delete('a');
4244

45+
expect(hashTable.delete('not-existing')).toBeNull();
46+
4347
expect(hashTable.get('a')).toBeNull();
44-
expect(hashTable.get('d').value).toBe('ocean');
48+
expect(hashTable.get('d')).toBe('ocean');
4549

4650
hashTable.insert('d', 'ocean-new');
47-
expect(hashTable.get('d').value).toBe('ocean-new');
51+
expect(hashTable.get('d')).toBe('ocean-new');
52+
});
53+
54+
it('should be possible to add objects to hash table', () => {
55+
const hashTable = new HashTable();
56+
57+
hashTable.insert('objectKey', { prop1: 'a', prop2: 'b' });
58+
59+
const object = hashTable.get('objectKey');
60+
expect(object).toBeDefined();
61+
expect(object.prop1).toBe('a');
62+
expect(object.prop2).toBe('b');
4863
});
4964
});

‎src/data-structures/linked-list/LinkedList.js

+27-88
Original file line numberDiff line numberDiff line change
@@ -2,74 +2,39 @@ import LinkedListNode from './LinkedListNode';
22

33
export default class LinkedList {
44
constructor() {
5+
/** @var LinkedListNode */
56
this.head = null;
7+
8+
/** @var LinkedListNode */
69
this.tail = null;
710
}
811

9-
prepend({ value, key = null }) {
10-
const newNode = new LinkedListNode({ value, key, next: this.head });
11-
12+
prepend(value) {
1213
// Make new node to be a head.
13-
this.head = newNode;
14+
this.head = new LinkedListNode(value, this.head);
1415

15-
return newNode;
16+
return this;
1617
}
1718

18-
append({ value, key = null }) {
19-
const newNode = new LinkedListNode({ value, key });
19+
append(value) {
20+
const newNode = new LinkedListNode(value);
2021

2122
// If there is no head yet let's make new node a head.
2223
if (!this.head) {
2324
this.head = newNode;
2425
this.tail = newNode;
2526

26-
return newNode;
27+
return this;
2728
}
2829

2930
// Attach new node to the end of linked list.
3031
this.tail.next = newNode;
3132
this.tail = newNode;
3233

33-
return newNode;
34+
return this;
3435
}
3536

36-
appendUnique({ value, key = null }) {
37-
const newNode = new LinkedListNode({ value, key });
38-
39-
// If there is no head yet let's make new node a head.
40-
if (!this.head) {
41-
this.head = newNode;
42-
this.tail = newNode;
43-
44-
return newNode;
45-
}
46-
47-
// Rewind to last node.
48-
let currentNode = this.head;
49-
while (currentNode.next !== null) {
50-
// If there is a node with specified key exists then update it instead of adding new one.
51-
if (key && currentNode.key === key) {
52-
currentNode.value = value;
53-
return currentNode;
54-
}
55-
56-
currentNode = currentNode.next;
57-
}
58-
59-
// If there is a node with specified key exists then update it instead of adding new one.
60-
if (key && currentNode.key === key) {
61-
currentNode.value = value;
62-
return currentNode;
63-
}
64-
65-
// Attach new node to the end of linked list.
66-
currentNode.next = newNode;
67-
this.tail = newNode;
68-
69-
return newNode;
70-
}
71-
72-
deleteByValue(value) {
37+
delete(value) {
7338
if (!this.head) {
7439
return null;
7540
}
@@ -102,37 +67,28 @@ export default class LinkedList {
10267
return deletedNode;
10368
}
10469

105-
deleteByKey(key) {
70+
find({ value = undefined, callback = undefined }) {
10671
if (!this.head) {
10772
return null;
10873
}
10974

110-
let deletedNode = null;
111-
112-
// If the head must be deleted then make 2nd node to be a head.
113-
if (this.head.key === key) {
114-
deletedNode = this.head;
115-
this.head = this.head.next;
116-
}
117-
11875
let currentNode = this.head;
11976

120-
// If next node must be deleted then make next node to be a next next one.
121-
while (currentNode.next) {
122-
if (currentNode.next.key === key) {
123-
deletedNode = currentNode.next;
124-
currentNode.next = currentNode.next.next;
125-
} else {
126-
currentNode = currentNode.next;
77+
while (currentNode) {
78+
// If callback is specified then try to find node by callback.
79+
if (callback && callback(currentNode.value)) {
80+
return currentNode;
12781
}
128-
}
12982

130-
// Check if tail must be deleted.
131-
if (this.tail.key === key) {
132-
this.tail = currentNode;
83+
// If value is specified then try to compare by value..
84+
if (value !== undefined && currentNode.value === value) {
85+
return currentNode;
86+
}
87+
88+
currentNode = currentNode.next;
13389
}
13490

135-
return deletedNode;
91+
return null;
13692
}
13793

13894
deleteTail() {
@@ -177,32 +133,15 @@ export default class LinkedList {
177133
return deletedHead;
178134
}
179135

180-
findByKey(key) {
181-
let currentNode = this.head;
136+
toString(callback) {
137+
const nodeStrings = [];
182138

183-
while (currentNode) {
184-
if (currentNode.key === key) {
185-
return currentNode;
186-
}
187-
currentNode = currentNode.next;
188-
}
189-
190-
return null;
191-
}
192-
193-
toArray() {
194-
const listArray = [];
195139
let currentNode = this.head;
196-
197140
while (currentNode) {
198-
listArray.push(currentNode.toString());
141+
nodeStrings.push(currentNode.toString(callback));
199142
currentNode = currentNode.next;
200143
}
201144

202-
return listArray;
203-
}
204-
205-
toString() {
206-
return this.toArray().toString();
145+
return nodeStrings.toString();
207146
}
208147
}
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,10 @@
11
export default class LinkedListNode {
2-
constructor({ value, next = null, key = null }) {
2+
constructor(value, next = null) {
33
this.value = value;
44
this.next = next;
5-
6-
// Key is added to make this linked list nodes to be reusable in hash tables.
7-
this.key = key;
85
}
96

10-
toString() {
11-
if (this.key) {
12-
return `${this.key}:${this.value}`;
13-
}
14-
15-
return `${this.value}`;
7+
toString(callback) {
8+
return callback ? callback(this.value) : `${this.value}`;
169
}
1710
}

0 commit comments

Comments
 (0)
Please sign in to comment.