Skip to content

Commit

Permalink
Add LinkedList traversal and reverse implementations (trekhleb#194)
Browse files Browse the repository at this point in the history
* Add LinkedList traverse function

* Add LinkedList reverse traversal implementations

* Update LinkedList traverse function

* Update LinkedList reverse traversal and test cases

* Update LinkedList traversal tests
  • Loading branch information
hanhdt authored and trekhleb committed Sep 8, 2018
1 parent d038c40 commit 4989a6a
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 5 deletions.
62 changes: 62 additions & 0 deletions src/data-structures/linked-list/LinkedList.js
Original file line number Diff line number Diff line change
Expand Up @@ -207,4 +207,66 @@ export default class LinkedList {
toString(callback) {
return this.toArray().map(node => node.toString(callback)).toString();
}

/**
* Traverse through all nodes of the list from head to tail
* @param {*} callback
* @return {LinkedListNode[]}
*/
traverse(callback = undefined) {
if (typeof callback !== 'function') {
throw new TypeError(`traverse method requires a callback function as an argument.\nArgument given: ${typeof callback}`);
}

let currentNode = this.head;
const traversedNodes = [];

while (currentNode) {
traversedNodes.push(callback(currentNode.value));
currentNode = currentNode.next;
}

return traversedNodes;
}

/**
* The items in the list have been traversed in reverse order
*/
reverseTraversal(node, callback = undefined) {
if (typeof callback !== 'function') {
throw new TypeError(`reverseTraverse method requires a callback function as an argument.\nArgument given: ${typeof callback}`);
}

if (!node) return [];

return this.reverseTraversal(node.next, callback).concat(callback(node.value));
}

/**
* Reverse a singly linked list use to three variables
* @returns {ReservedLinkedList}
*/
reverse() {
let currNode = this.head;
let prevNode = null;
let nextNode = null;

while (currNode) {
// Store next node
nextNode = currNode.next;

// Change next node of the current
currNode.next = prevNode;

// Move forward prev and current nodes one step
prevNode = currNode;
currNode = nextNode;
}

// Reset head, tail
this.tail = this.head;
this.head = prevNode;

return this;
}
}
10 changes: 5 additions & 5 deletions src/data-structures/linked-list/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,24 +110,24 @@ Traverse(head)
Pre: head is the head node in the list
Post: the items in the list have been traversed
n ← head
while n = 0
while n != ø
yield n.value
n ← n.next
end while
end Traverse
```

### Traverse in Reverse

```text
ReverseTraversal(head, tail)
Pre: head and tail belong to the same list
Post: the items in the list have been traversed in reverse order
if tail = ø
if tail != ø
curr ← tail
while curr = head
while curr != head
prev ← head
while prev.next = curr
while prev.next != curr
prev ← prev.next
end while
yield curr.value
Expand Down
37 changes: 37 additions & 0 deletions src/data-structures/linked-list/__test__/LinkedList.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,4 +217,41 @@ describe('LinkedList', () => {
expect(node.value.customValue).toBe('test2');
expect(linkedList.find({ value: 2, customValue: 'test5' })).toBeNull();
});

it('should traverse through all nodes of the list from head to tail with callback', () => {
const linkedList = new LinkedList();

linkedList
.append(1)
.append(2)
.append(3);

expect(linkedList.traverse(value => value * 2)).toEqual([2, 4, 6]);
expect(() => linkedList.traverse()).toThrow();
});

it('should reverse traversal the linked list with callback', () => {
const linkedList = new LinkedList();

linkedList
.append(1)
.append(2)
.append(3);

expect(linkedList.toString()).toBe('1,2,3');
expect(linkedList.reverseTraversal(linkedList.head, value => value * 2)).toEqual([6, 4, 2]);
expect(() => linkedList.reverseTraversal(linkedList.head)).toThrow();
});

it('should reverse the singly linked list', () => {
const linkedList = new LinkedList();

linkedList
.append(1)
.append(2)
.append(3);

expect(linkedList.toString()).toBe('1,2,3');
expect(linkedList.reverse().toString()).toBe('3,2,1');
});
});

0 comments on commit 4989a6a

Please sign in to comment.