From 3303051d75056da20a839314bc59f08d3ce73ac7 Mon Sep 17 00:00:00 2001 From: Yair Temkin Date: Fri, 28 Jan 2022 15:26:39 -0500 Subject: [PATCH 1/2] Inserting, removing, accessing, modifying, by index, on linked list with tests --- src/data-structures/linked-list/LinkedList.js | 76 +++++++++++++++- .../linked-list/__test__/LinkedList.test.js | 88 ++++++++++++++++--- 2 files changed, 150 insertions(+), 14 deletions(-) diff --git a/src/data-structures/linked-list/LinkedList.js b/src/data-structures/linked-list/LinkedList.js index ba7d0e3e..f3e429d4 100644 --- a/src/data-structures/linked-list/LinkedList.js +++ b/src/data-structures/linked-list/LinkedList.js @@ -87,6 +87,28 @@ export default class LinkedList { } return this; } + /** + * @param {*} value + * @param {number} index + * @return {LinkedList} + */ + setAtIndex(value, index) { + if (index < 0) { + return this; + } else { + let count = 0; + let currentNode = this.head; + while (currentNode) { + if (count === index) break; + currentNode = currentNode.next; + count += 1; + } + if (currentNode) { + currentNode.value = value; + } + return this; + } + } /** * @param {*} value @@ -128,6 +150,36 @@ export default class LinkedList { return deletedNode; } + /** + * @param {number} index + * @return {LinkedListNode} + */ + deleteAtIndex(index) { + if (!this.head || index < 0) { + return null; + } + let deletedNode = null; + if (index === 0) { + deletedNode = this.head; + this.head = this.head.next; + } else { + let count = 1; + let currentNode = this.head; + while (currentNode) { + if (count === index) break; + currentNode = currentNode.next; + count += 1; + } + if (currentNode) { + deletedNode = currentNode.next; + if (deletedNode) { + currentNode.next = deletedNode.next; + } + } + } + return deletedNode; + } + /** * @param {Object} findParams * @param {*} findParams.value @@ -158,6 +210,26 @@ export default class LinkedList { return null; } + /** + * @param {*} index + * @return {LinkedListNode} + */ + findByIndex(index) { + if (!this.head || index < 0) { + return null; + } else if (index === 0) { + return this.head; + } + let count = 0; + let currentNode = this.head; + while (currentNode) { + if (count === index) break; + currentNode = currentNode.next; + count += 1; + } + return currentNode; + } + /** * @return {LinkedListNode} */ @@ -239,7 +311,9 @@ export default class LinkedList { * @return {string} */ toString(callback) { - return this.toArray().map((node) => node.toString(callback)).toString(); + return this.toArray() + .map((node) => node.toString(callback)) + .toString(); } /** diff --git a/src/data-structures/linked-list/__test__/LinkedList.test.js b/src/data-structures/linked-list/__test__/LinkedList.test.js index 6ac41ddf..9bce6bcf 100644 --- a/src/data-structures/linked-list/__test__/LinkedList.test.js +++ b/src/data-structures/linked-list/__test__/LinkedList.test.js @@ -47,6 +47,26 @@ describe('LinkedList', () => { expect(linkedList.toString()).toBe('1,4,2,3,10'); }); + it('should insert node to linked list', () => { + const linkedList = new LinkedList(); + + linkedList.append(1).append(2).append(3).append(4).append(5); + + expect(linkedList.toString()).toBe('1,2,3,4,5'); + + linkedList.setAtIndex(5, -2); + expect(linkedList.toString()).toBe('1,2,3,4,5'); + + linkedList.setAtIndex(12, 3); + expect(linkedList.toString()).toBe('1,2,3,12,5'); + + linkedList.setAtIndex(55, 0); + expect(linkedList.toString()).toBe('55,2,3,12,5'); + + linkedList.setAtIndex(0, 55); + expect(linkedList.toString()).toBe('55,2,3,12,5'); + }); + it('should delete node by value from linked list', () => { const linkedList = new LinkedList(); @@ -93,6 +113,34 @@ describe('LinkedList', () => { expect(linkedList.toString()).toBe(''); }); + it('should delete node at index from linked list', () => { + const linkedList = new LinkedList(); + + expect(linkedList.delete(5)).toBeNull(); + + linkedList.append(1); + linkedList.append(2); + linkedList.append(3); + linkedList.append(4); + linkedList.append(5); + + expect(linkedList.head.toString()).toBe('1'); + expect(linkedList.tail.toString()).toBe('5'); + + let deletedNode = linkedList.deleteAtIndex(3); + expect(deletedNode.value).toBe(4); + expect(linkedList.toString()).toBe('1,2,3,5'); + + linkedList.deleteAtIndex(1); + expect(linkedList.toString()).toBe('1,3,5'); + + deletedNode = linkedList.delete(-5); + expect(deletedNode).toBeNull(); + + deletedNode = linkedList.delete(10); + expect(deletedNode).toBeNull(); + }); + it('should delete linked list tail', () => { const linkedList = new LinkedList(); @@ -157,9 +205,7 @@ describe('LinkedList', () => { const nodeValue1 = { value: 1, key: 'key1' }; const nodeValue2 = { value: 2, key: 'key2' }; - linkedList - .append(nodeValue1) - .prepend(nodeValue2); + linkedList.append(nodeValue1).prepend(nodeValue2); const nodeStringifier = (value) => `${value.key}:${value.value}`; @@ -174,9 +220,7 @@ describe('LinkedList', () => { linkedList.append(1); expect(linkedList.find({ value: 1 })).toBeDefined(); - linkedList - .append(2) - .append(3); + linkedList.append(2).append(3); const node = linkedList.find({ value: 2 }); @@ -184,6 +228,21 @@ describe('LinkedList', () => { expect(linkedList.find({ value: 5 })).toBeNull(); }); + it('should find node by index', () => { + const linkedList = new LinkedList(); + + expect(linkedList.findByIndex(5)).toBeNull(); + linkedList.append(1); + expect(linkedList.findByIndex(0).value).toBe(1); + + linkedList.append(2).append(3); + + const node = linkedList.findByIndex(2); + expect(node.value).toBe(3); + expect(linkedList.findByIndex(5)).toBeNull(); + expect(linkedList.findByIndex(-3)).toBeNull(); + }); + it('should find node by callback', () => { const linkedList = new LinkedList(); @@ -192,12 +251,16 @@ describe('LinkedList', () => { .append({ value: 2, key: 'test2' }) .append({ value: 3, key: 'test3' }); - const node = linkedList.find({ callback: (value) => value.key === 'test2' }); + const node = linkedList.find({ + callback: (value) => value.key === 'test2', + }); expect(node).toBeDefined(); expect(node.value.value).toBe(2); expect(node.value.key).toBe('test2'); - expect(linkedList.find({ callback: (value) => value.key === 'test5' })).toBeNull(); + expect( + linkedList.find({ callback: (value) => value.key === 'test5' }) + ).toBeNull(); }); it('should create linked list from array', () => { @@ -230,7 +293,9 @@ describe('LinkedList', () => { expect(node).toBeDefined(); expect(node.value.value).toBe(2); expect(node.value.customValue).toBe('test2'); - expect(linkedList.find({ value: { value: 2, customValue: 'test5' } })).toBeNull(); + expect( + linkedList.find({ value: { value: 2, customValue: 'test5' } }) + ).toBeNull(); }); it('should find preferring callback over compare function', () => { @@ -258,10 +323,7 @@ describe('LinkedList', () => { const linkedList = new LinkedList(); // Add test values to linked list. - linkedList - .append(1) - .append(2) - .append(3); + linkedList.append(1).append(2).append(3); expect(linkedList.toString()).toBe('1,2,3'); expect(linkedList.head.value).toBe(1); From c66bd96b651d043f8dc46880a38fdc2bccdf72b7 Mon Sep 17 00:00:00 2001 From: Yair Temkin Date: Sat, 29 Jan 2022 11:13:45 -0500 Subject: [PATCH 2/2] Inserting, removing, accessing, modifying, by index, on linked list with tests --- src/data-structures/linked-list/LinkedList.js | 26 +++++++++---------- .../linked-list/__test__/LinkedList.test.js | 10 ++++--- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/data-structures/linked-list/LinkedList.js b/src/data-structures/linked-list/LinkedList.js index f3e429d4..85fe920d 100644 --- a/src/data-structures/linked-list/LinkedList.js +++ b/src/data-structures/linked-list/LinkedList.js @@ -87,6 +87,7 @@ export default class LinkedList { } return this; } + /** * @param {*} value * @param {number} index @@ -95,19 +96,18 @@ export default class LinkedList { setAtIndex(value, index) { if (index < 0) { return this; - } else { - let count = 0; - let currentNode = this.head; - while (currentNode) { - if (count === index) break; - currentNode = currentNode.next; - count += 1; - } - if (currentNode) { - currentNode.value = value; - } - return this; } + let count = 0; + let currentNode = this.head; + while (currentNode) { + if (count === index) break; + currentNode = currentNode.next; + count += 1; + } + if (currentNode) { + currentNode.value = value; + } + return this; } /** @@ -217,8 +217,6 @@ export default class LinkedList { findByIndex(index) { if (!this.head || index < 0) { return null; - } else if (index === 0) { - return this.head; } let count = 0; let currentNode = this.head; diff --git a/src/data-structures/linked-list/__test__/LinkedList.test.js b/src/data-structures/linked-list/__test__/LinkedList.test.js index 9bce6bcf..776731e7 100644 --- a/src/data-structures/linked-list/__test__/LinkedList.test.js +++ b/src/data-structures/linked-list/__test__/LinkedList.test.js @@ -50,7 +50,11 @@ describe('LinkedList', () => { it('should insert node to linked list', () => { const linkedList = new LinkedList(); - linkedList.append(1).append(2).append(3).append(4).append(5); + linkedList.append(1); + linkedList.append(2); + linkedList.append(3); + linkedList.append(4); + linkedList.append(5); expect(linkedList.toString()).toBe('1,2,3,4,5'); @@ -259,7 +263,7 @@ describe('LinkedList', () => { expect(node.value.value).toBe(2); expect(node.value.key).toBe('test2'); expect( - linkedList.find({ callback: (value) => value.key === 'test5' }) + linkedList.find({ callback: (value) => value.key === 'test5' }), ).toBeNull(); }); @@ -294,7 +298,7 @@ describe('LinkedList', () => { expect(node.value.value).toBe(2); expect(node.value.customValue).toBe('test2'); expect( - linkedList.find({ value: { value: 2, customValue: 'test5' } }) + linkedList.find({ value: { value: 2, customValue: 'test5' } }), ).toBeNull(); });