UNPKG

@dxzmpk/js-algorithms-data-structures

Version:

Algorithms and data-structures implemented on JavaScript

281 lines (206 loc) 8.55 kB
import DoublyLinkedList from '../DoublyLinkedList'; describe('DoublyLinkedList', () => { it('should create empty linked list', () => { const linkedList = new DoublyLinkedList(); expect(linkedList.toString()).toBe(''); }); it('should append node to linked list', () => { const linkedList = new DoublyLinkedList(); expect(linkedList.head).toBeNull(); expect(linkedList.tail).toBeNull(); linkedList.append(1); linkedList.append(2); expect(linkedList.head.next.value).toBe(2); expect(linkedList.tail.previous.value).toBe(1); expect(linkedList.toString()).toBe('1,2'); }); it('should prepend node to linked list', () => { const linkedList = new DoublyLinkedList(); linkedList.prepend(2); expect(linkedList.head.toString()).toBe('2'); expect(linkedList.tail.toString()).toBe('2'); linkedList.append(1); linkedList.prepend(3); expect(linkedList.head.next.next.previous).toBe(linkedList.head.next); expect(linkedList.tail.previous.next).toBe(linkedList.tail); expect(linkedList.tail.previous.value).toBe(2); expect(linkedList.toString()).toBe('3,2,1'); }); it('should create linked list from array', () => { const linkedList = new DoublyLinkedList(); linkedList.fromArray([1, 1, 2, 3, 3, 3, 4, 5]); expect(linkedList.toString()).toBe('1,1,2,3,3,3,4,5'); }); it('should delete node by value from linked list', () => { const linkedList = new DoublyLinkedList(); expect(linkedList.delete(5)).toBeNull(); linkedList.append(1); linkedList.append(1); linkedList.append(2); linkedList.append(3); linkedList.append(3); linkedList.append(3); linkedList.append(4); linkedList.append(5); expect(linkedList.head.toString()).toBe('1'); expect(linkedList.tail.toString()).toBe('5'); const deletedNode = linkedList.delete(3); expect(deletedNode.value).toBe(3); expect(linkedList.tail.previous.previous.value).toBe(2); expect(linkedList.toString()).toBe('1,1,2,4,5'); linkedList.delete(3); expect(linkedList.toString()).toBe('1,1,2,4,5'); linkedList.delete(1); expect(linkedList.toString()).toBe('2,4,5'); expect(linkedList.head.toString()).toBe('2'); expect(linkedList.head.next.next).toBe(linkedList.tail); expect(linkedList.tail.previous.previous).toBe(linkedList.head); expect(linkedList.tail.toString()).toBe('5'); linkedList.delete(5); expect(linkedList.toString()).toBe('2,4'); expect(linkedList.head.toString()).toBe('2'); expect(linkedList.tail.toString()).toBe('4'); linkedList.delete(4); expect(linkedList.toString()).toBe('2'); expect(linkedList.head.toString()).toBe('2'); expect(linkedList.tail.toString()).toBe('2'); expect(linkedList.head).toBe(linkedList.tail); linkedList.delete(2); expect(linkedList.toString()).toBe(''); }); it('should delete linked list tail', () => { const linkedList = new DoublyLinkedList(); expect(linkedList.deleteTail()).toBeNull(); linkedList.append(1); linkedList.append(2); linkedList.append(3); expect(linkedList.head.toString()).toBe('1'); expect(linkedList.tail.toString()).toBe('3'); const deletedNode1 = linkedList.deleteTail(); expect(deletedNode1.value).toBe(3); expect(linkedList.toString()).toBe('1,2'); expect(linkedList.head.toString()).toBe('1'); expect(linkedList.tail.toString()).toBe('2'); const deletedNode2 = linkedList.deleteTail(); expect(deletedNode2.value).toBe(2); expect(linkedList.toString()).toBe('1'); expect(linkedList.head.toString()).toBe('1'); expect(linkedList.tail.toString()).toBe('1'); const deletedNode3 = linkedList.deleteTail(); expect(deletedNode3.value).toBe(1); expect(linkedList.toString()).toBe(''); expect(linkedList.head).toBeNull(); expect(linkedList.tail).toBeNull(); }); it('should delete linked list head', () => { const linkedList = new DoublyLinkedList(); expect(linkedList.deleteHead()).toBeNull(); linkedList.append(1); linkedList.append(2); expect(linkedList.head.toString()).toBe('1'); expect(linkedList.tail.toString()).toBe('2'); const deletedNode1 = linkedList.deleteHead(); expect(deletedNode1.value).toBe(1); expect(linkedList.head.previous).toBeNull(); expect(linkedList.toString()).toBe('2'); expect(linkedList.head.toString()).toBe('2'); expect(linkedList.tail.toString()).toBe('2'); const deletedNode2 = linkedList.deleteHead(); expect(deletedNode2.value).toBe(2); expect(linkedList.toString()).toBe(''); expect(linkedList.head).toBeNull(); expect(linkedList.tail).toBeNull(); }); it('should be possible to store objects in the list and to print them out', () => { const linkedList = new DoublyLinkedList(); const nodeValue1 = { value: 1, key: 'key1' }; const nodeValue2 = { value: 2, key: 'key2' }; linkedList .append(nodeValue1) .prepend(nodeValue2); const nodeStringifier = (value) => `${value.key}:${value.value}`; expect(linkedList.toString(nodeStringifier)).toBe('key2:2,key1:1'); }); it('should find node by value', () => { const linkedList = new DoublyLinkedList(); expect(linkedList.find({ value: 5 })).toBeNull(); linkedList.append(1); expect(linkedList.find({ value: 1 })).toBeDefined(); linkedList .append(2) .append(3); const node = linkedList.find({ value: 2 }); expect(node.value).toBe(2); expect(linkedList.find({ value: 5 })).toBeNull(); }); it('should find node by callback', () => { const linkedList = new DoublyLinkedList(); linkedList .append({ value: 1, key: 'test1' }) .append({ value: 2, key: 'test2' }) .append({ value: 3, key: 'test3' }); 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(); }); it('should find node by means of custom compare function', () => { const comparatorFunction = (a, b) => { if (a.customValue === b.customValue) { return 0; } return a.customValue < b.customValue ? -1 : 1; }; const linkedList = new DoublyLinkedList(comparatorFunction); linkedList .append({ value: 1, customValue: 'test1' }) .append({ value: 2, customValue: 'test2' }) .append({ value: 3, customValue: 'test3' }); const node = linkedList.find({ value: { value: 2, customValue: 'test2' }, }); expect(node).toBeDefined(); expect(node.value.value).toBe(2); expect(node.value.customValue).toBe('test2'); expect(linkedList.find({ value: 2, customValue: 'test5' })).toBeNull(); }); it('should reverse linked list', () => { const linkedList = new DoublyLinkedList(); // Add test values to linked list. linkedList .append(1) .append(2) .append(3) .append(4); expect(linkedList.toString()).toBe('1,2,3,4'); expect(linkedList.head.value).toBe(1); expect(linkedList.tail.value).toBe(4); // Reverse linked list. linkedList.reverse(); expect(linkedList.toString()).toBe('4,3,2,1'); expect(linkedList.head.previous).toBeNull(); expect(linkedList.head.value).toBe(4); expect(linkedList.head.next.value).toBe(3); expect(linkedList.head.next.next.value).toBe(2); expect(linkedList.head.next.next.next.value).toBe(1); expect(linkedList.tail.next).toBeNull(); expect(linkedList.tail.value).toBe(1); expect(linkedList.tail.previous.value).toBe(2); expect(linkedList.tail.previous.previous.value).toBe(3); expect(linkedList.tail.previous.previous.previous.value).toBe(4); // Reverse linked list back to initial state. linkedList.reverse(); expect(linkedList.toString()).toBe('1,2,3,4'); expect(linkedList.head.previous).toBeNull(); expect(linkedList.head.value).toBe(1); expect(linkedList.head.next.value).toBe(2); expect(linkedList.head.next.next.value).toBe(3); expect(linkedList.head.next.next.next.value).toBe(4); expect(linkedList.tail.next).toBeNull(); expect(linkedList.tail.value).toBe(4); expect(linkedList.tail.previous.value).toBe(3); expect(linkedList.tail.previous.previous.value).toBe(2); expect(linkedList.tail.previous.previous.previous.value).toBe(1); }); });