mirror of
https://github.moeyy.xyz/https://github.com/trekhleb/javascript-algorithms.git
synced 2024-12-26 23:21:18 +08:00
Add LinkedList traversal and reverse implementations (#194)
* Add LinkedList traverse function * Add LinkedList reverse traversal implementations * Update LinkedList traverse function * Update LinkedList reverse traversal and test cases * Update LinkedList traversal tests
This commit is contained in:
parent
d038c402dd
commit
4989a6a3b0
@ -207,4 +207,66 @@ export default class LinkedList {
|
|||||||
toString(callback) {
|
toString(callback) {
|
||||||
return this.toArray().map(node => node.toString(callback)).toString();
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ Traverse(head)
|
|||||||
Pre: head is the head node in the list
|
Pre: head is the head node in the list
|
||||||
Post: the items in the list have been traversed
|
Post: the items in the list have been traversed
|
||||||
n ← head
|
n ← head
|
||||||
while n = 0
|
while n != ø
|
||||||
yield n.value
|
yield n.value
|
||||||
n ← n.next
|
n ← n.next
|
||||||
end while
|
end while
|
||||||
@ -123,11 +123,11 @@ end Traverse
|
|||||||
ReverseTraversal(head, tail)
|
ReverseTraversal(head, tail)
|
||||||
Pre: head and tail belong to the same list
|
Pre: head and tail belong to the same list
|
||||||
Post: the items in the list have been traversed in reverse order
|
Post: the items in the list have been traversed in reverse order
|
||||||
if tail = ø
|
if tail != ø
|
||||||
curr ← tail
|
curr ← tail
|
||||||
while curr = head
|
while curr != head
|
||||||
prev ← head
|
prev ← head
|
||||||
while prev.next = curr
|
while prev.next != curr
|
||||||
prev ← prev.next
|
prev ← prev.next
|
||||||
end while
|
end while
|
||||||
yield curr.value
|
yield curr.value
|
||||||
|
@ -217,4 +217,41 @@ describe('LinkedList', () => {
|
|||||||
expect(node.value.customValue).toBe('test2');
|
expect(node.value.customValue).toBe('test2');
|
||||||
expect(linkedList.find({ value: 2, customValue: 'test5' })).toBeNull();
|
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');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user