mirror of
https://github.moeyy.xyz/https://github.com/trekhleb/javascript-algorithms.git
synced 2024-11-14 06:52:59 +08:00
Move linked list traversals into separate section.
This commit is contained in:
parent
2feec48ea6
commit
80ecbe0b3e
@ -109,6 +109,9 @@ a set of rules that precisely define a sequence of operations.
|
|||||||
* `B` [Shellsort](src/algorithms/sorting/shell-sort)
|
* `B` [Shellsort](src/algorithms/sorting/shell-sort)
|
||||||
* `B` [Counting Sort](src/algorithms/sorting/counting-sort)
|
* `B` [Counting Sort](src/algorithms/sorting/counting-sort)
|
||||||
* `B` [Radix Sort](src/algorithms/sorting/radix-sort)
|
* `B` [Radix Sort](src/algorithms/sorting/radix-sort)
|
||||||
|
* **Linked Lists**
|
||||||
|
* `B` [Straight Traversal](src/algorithms/linked-list/traversal)
|
||||||
|
* `B` [Reverse Traversal](src/algorithms/linked-list/reverse-traversal)
|
||||||
* **Trees**
|
* **Trees**
|
||||||
* `B` [Depth-First Search](src/algorithms/tree/depth-first-search) (DFS)
|
* `B` [Depth-First Search](src/algorithms/tree/depth-first-search) (DFS)
|
||||||
* `B` [Breadth-First Search](src/algorithms/tree/breadth-first-search) (BFS)
|
* `B` [Breadth-First Search](src/algorithms/tree/breadth-first-search) (BFS)
|
||||||
|
19
src/algorithms/linked-list/reverse-traversal/README.md
Normal file
19
src/algorithms/linked-list/reverse-traversal/README.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Reversed Linked List Traversal
|
||||||
|
|
||||||
|
The task is to traverse the given linked list in reversed order.
|
||||||
|
|
||||||
|
For example for the following linked list:
|
||||||
|
|
||||||
|
![](https://upload.wikimedia.org/wikipedia/commons/6/6d/Singly-linked-list.svg)
|
||||||
|
|
||||||
|
The order of traversal should be:
|
||||||
|
|
||||||
|
```text
|
||||||
|
37 → 99 → 12
|
||||||
|
```
|
||||||
|
|
||||||
|
The time complexity is `O(n)` because we visit every node only once.
|
||||||
|
|
||||||
|
## Reference
|
||||||
|
|
||||||
|
- [Wikipedia](https://en.wikipedia.org/wiki/Linked_list)
|
@ -0,0 +1,36 @@
|
|||||||
|
import LinkedList from '../../../../data-structures/linked-list/LinkedList';
|
||||||
|
import reverseTraversal from '../reverseTraversal';
|
||||||
|
|
||||||
|
describe('reverseTraversal', () => {
|
||||||
|
it('should traverse linked list in reverse order', () => {
|
||||||
|
const linkedList = new LinkedList();
|
||||||
|
|
||||||
|
linkedList
|
||||||
|
.append(1)
|
||||||
|
.append(2)
|
||||||
|
.append(3);
|
||||||
|
|
||||||
|
const traversedNodeValues = [];
|
||||||
|
const traversalCallback = (nodeValue) => {
|
||||||
|
traversedNodeValues.push(nodeValue);
|
||||||
|
};
|
||||||
|
|
||||||
|
reverseTraversal(linkedList, traversalCallback);
|
||||||
|
|
||||||
|
expect(traversedNodeValues).toEqual([3, 2, 1]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
// });
|
@ -0,0 +1,24 @@
|
|||||||
|
/**
|
||||||
|
* Traversal callback function.
|
||||||
|
* @callback traversalCallback
|
||||||
|
* @param {*} nodeValue
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {LinkedListNode} node
|
||||||
|
* @param {traversalCallback} callback
|
||||||
|
*/
|
||||||
|
function reverseTraversalRecursive(node, callback) {
|
||||||
|
if (node) {
|
||||||
|
reverseTraversalRecursive(node.next, callback);
|
||||||
|
callback(node.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {LinkedList} linkedList
|
||||||
|
* @param {traversalCallback} callback
|
||||||
|
*/
|
||||||
|
export default function reverseTraversal(linkedList, callback) {
|
||||||
|
reverseTraversalRecursive(linkedList.head, callback);
|
||||||
|
}
|
19
src/algorithms/linked-list/traversal/README.md
Normal file
19
src/algorithms/linked-list/traversal/README.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Linked List Traversal
|
||||||
|
|
||||||
|
The task is to traverse the given linked list in straight order.
|
||||||
|
|
||||||
|
For example for the following linked list:
|
||||||
|
|
||||||
|
![](https://upload.wikimedia.org/wikipedia/commons/6/6d/Singly-linked-list.svg)
|
||||||
|
|
||||||
|
The order of traversal should be:
|
||||||
|
|
||||||
|
```text
|
||||||
|
12 → 99 → 37
|
||||||
|
```
|
||||||
|
|
||||||
|
The time complexity is `O(n)` because we visit every node only once.
|
||||||
|
|
||||||
|
## Reference
|
||||||
|
|
||||||
|
- [Wikipedia](https://en.wikipedia.org/wiki/Linked_list)
|
@ -0,0 +1,22 @@
|
|||||||
|
import LinkedList from '../../../../data-structures/linked-list/LinkedList';
|
||||||
|
import traversal from '../traversal';
|
||||||
|
|
||||||
|
describe('traversal', () => {
|
||||||
|
it('should traverse linked list', () => {
|
||||||
|
const linkedList = new LinkedList();
|
||||||
|
|
||||||
|
linkedList
|
||||||
|
.append(1)
|
||||||
|
.append(2)
|
||||||
|
.append(3);
|
||||||
|
|
||||||
|
const traversedNodeValues = [];
|
||||||
|
const traversalCallback = (nodeValue) => {
|
||||||
|
traversedNodeValues.push(nodeValue);
|
||||||
|
};
|
||||||
|
|
||||||
|
traversal(linkedList, traversalCallback);
|
||||||
|
|
||||||
|
expect(traversedNodeValues).toEqual([1, 2, 3]);
|
||||||
|
});
|
||||||
|
});
|
18
src/algorithms/linked-list/traversal/traversal.js
Normal file
18
src/algorithms/linked-list/traversal/traversal.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* Traversal callback function.
|
||||||
|
* @callback traversalCallback
|
||||||
|
* @param {*} nodeValue
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {LinkedList} linkedList
|
||||||
|
* @param {traversalCallback} callback
|
||||||
|
*/
|
||||||
|
export default function traversal(linkedList, callback) {
|
||||||
|
let currentNode = linkedList.head;
|
||||||
|
|
||||||
|
while (currentNode) {
|
||||||
|
callback(currentNode.value);
|
||||||
|
currentNode = currentNode.next;
|
||||||
|
}
|
||||||
|
}
|
@ -208,40 +208,6 @@ export default class LinkedList {
|
|||||||
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 linked list.
|
* Reverse a linked list.
|
||||||
* @returns {LinkedList}
|
* @returns {LinkedList}
|
||||||
|
@ -218,31 +218,6 @@ describe('LinkedList', () => {
|
|||||||
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 linked list', () => {
|
it('should reverse linked list', () => {
|
||||||
const linkedList = new LinkedList();
|
const linkedList = new LinkedList();
|
||||||
|
|
||||||
@ -258,9 +233,14 @@ describe('LinkedList', () => {
|
|||||||
|
|
||||||
// Reverse linked list.
|
// Reverse linked list.
|
||||||
linkedList.reverse();
|
linkedList.reverse();
|
||||||
|
|
||||||
expect(linkedList.toString()).toBe('3,2,1');
|
expect(linkedList.toString()).toBe('3,2,1');
|
||||||
expect(linkedList.head.value).toBe(3);
|
expect(linkedList.head.value).toBe(3);
|
||||||
expect(linkedList.tail.value).toBe(1);
|
expect(linkedList.tail.value).toBe(1);
|
||||||
|
|
||||||
|
// Reverse linked list back to initial state.
|
||||||
|
linkedList.reverse();
|
||||||
|
expect(linkedList.toString()).toBe('1,2,3');
|
||||||
|
expect(linkedList.head.value).toBe(1);
|
||||||
|
expect(linkedList.tail.value).toBe(3);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user