mirror of
https://github.moeyy.xyz/https://github.com/trekhleb/javascript-algorithms.git
synced 2024-12-26 23:21:18 +08:00
Add Stack.
This commit is contained in:
parent
159d489e52
commit
8da6754523
@ -4,9 +4,9 @@
|
|||||||
|
|
||||||
## Data Structures
|
## Data Structures
|
||||||
|
|
||||||
- [Linked List](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/linked-list)
|
1. [Linked List](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/linked-list)
|
||||||
- [Hash Table](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/hash-table)
|
2. [Queue](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/queue)
|
||||||
- [Queue](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/queue)
|
3. [Hash Table](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/hash-table)
|
||||||
|
|
||||||
## Running Tests
|
## Running Tests
|
||||||
|
|
||||||
|
@ -160,6 +160,23 @@ export default class LinkedList {
|
|||||||
return deletedTail;
|
return deletedTail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deleteHead() {
|
||||||
|
if (!this.head) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const deletedHead = this.head;
|
||||||
|
|
||||||
|
if (this.head.next) {
|
||||||
|
this.head = this.head.next;
|
||||||
|
} else {
|
||||||
|
this.head = null;
|
||||||
|
this.tail = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return deletedHead;
|
||||||
|
}
|
||||||
|
|
||||||
findByKey(key) {
|
findByKey(key) {
|
||||||
let currentNode = this.head;
|
let currentNode = this.head;
|
||||||
|
|
||||||
|
@ -43,6 +43,8 @@ describe('LinkedList', () => {
|
|||||||
it('should delete node by value from linked list', () => {
|
it('should delete node by value from linked list', () => {
|
||||||
const linkedList = new LinkedList();
|
const linkedList = new LinkedList();
|
||||||
|
|
||||||
|
expect(linkedList.deleteByValue(5)).toBeNull();
|
||||||
|
|
||||||
linkedList.append({ value: 1 });
|
linkedList.append({ value: 1 });
|
||||||
linkedList.append({ value: 2 });
|
linkedList.append({ value: 2 });
|
||||||
linkedList.append({ value: 3 });
|
linkedList.append({ value: 3 });
|
||||||
@ -80,55 +82,103 @@ describe('LinkedList', () => {
|
|||||||
expect(linkedList.tail.toString()).toBe('2');
|
expect(linkedList.tail.toString()).toBe('2');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should delete node by key from linked list', () => {
|
||||||
|
const linkedList = new LinkedList();
|
||||||
|
|
||||||
|
expect(linkedList.deleteByKey('key')).toBeNull();
|
||||||
|
|
||||||
|
linkedList.append({ value: 1, key: 'test1' });
|
||||||
|
linkedList.append({ value: 2, key: 'test2' });
|
||||||
|
linkedList.append({ value: 3, key: 'test3' });
|
||||||
|
linkedList.append({ value: 4, key: 'test4' });
|
||||||
|
|
||||||
|
const deletedNode1 = linkedList.deleteByKey('test2');
|
||||||
|
expect(deletedNode1.key).toBe('test2');
|
||||||
|
expect(linkedList.toString()).toBe('test1:1,test3:3,test4:4');
|
||||||
|
|
||||||
|
const deletedNode2 = linkedList.deleteByKey('test1');
|
||||||
|
expect(deletedNode2.key).toBe('test1');
|
||||||
|
expect(linkedList.toString()).toBe('test3:3,test4:4');
|
||||||
|
|
||||||
|
const deletedNode3 = linkedList.deleteByKey('test4');
|
||||||
|
expect(deletedNode3.key).toBe('test4');
|
||||||
|
expect(linkedList.toString()).toBe('test3:3');
|
||||||
|
});
|
||||||
|
|
||||||
it('should delete linked list tail', () => {
|
it('should delete linked list tail', () => {
|
||||||
const linkedList = new LinkedList();
|
const linkedList = new LinkedList();
|
||||||
|
|
||||||
|
linkedList.append({ value: 1 });
|
||||||
|
linkedList.append({ value: 2 });
|
||||||
|
linkedList.append({ value: 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 LinkedList();
|
||||||
|
|
||||||
|
expect(linkedList.deleteHead()).toBeNull();
|
||||||
|
|
||||||
linkedList.append({ value: 1 });
|
linkedList.append({ value: 1 });
|
||||||
linkedList.append({ value: 2 });
|
linkedList.append({ value: 2 });
|
||||||
|
|
||||||
expect(linkedList.head.toString()).toBe('1');
|
expect(linkedList.head.toString()).toBe('1');
|
||||||
expect(linkedList.tail.toString()).toBe('2');
|
expect(linkedList.tail.toString()).toBe('2');
|
||||||
|
|
||||||
const deletedNode1 = linkedList.deleteTail();
|
const deletedNode1 = linkedList.deleteHead();
|
||||||
|
|
||||||
expect(deletedNode1.value).toBe(2);
|
expect(deletedNode1.value).toBe(1);
|
||||||
expect(linkedList.toString()).toBe('1');
|
expect(linkedList.toString()).toBe('2');
|
||||||
expect(linkedList.head.toString()).toBe('1');
|
expect(linkedList.head.toString()).toBe('2');
|
||||||
expect(linkedList.tail.toString()).toBe('1');
|
expect(linkedList.tail.toString()).toBe('2');
|
||||||
|
|
||||||
const deletedNode2 = linkedList.deleteTail();
|
const deletedNode2 = linkedList.deleteHead();
|
||||||
|
|
||||||
expect(deletedNode2.value).toBe(1);
|
expect(deletedNode2.value).toBe(2);
|
||||||
expect(linkedList.toString()).toBe('');
|
expect(linkedList.toString()).toBe('');
|
||||||
expect(linkedList.head).toBeNull();
|
expect(linkedList.head).toBeNull();
|
||||||
expect(linkedList.tail).toBeNull();
|
expect(linkedList.tail).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should delete node by key from linked list', () => {
|
|
||||||
const linkedList = new LinkedList();
|
|
||||||
|
|
||||||
linkedList.append({ value: 1, key: 'test1' });
|
|
||||||
linkedList.append({ value: 2, key: 'test2' });
|
|
||||||
linkedList.append({ value: 3, key: 'test3' });
|
|
||||||
|
|
||||||
const deletedNode = linkedList.deleteByKey('test2');
|
|
||||||
expect(deletedNode.key).toBe('test2');
|
|
||||||
expect(linkedList.toString()).toBe('test1:1,test3:3');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should append unique nodes', () => {
|
it('should append unique nodes', () => {
|
||||||
const linkedList = new LinkedList();
|
const linkedList = new LinkedList();
|
||||||
|
|
||||||
linkedList.appendUnique({ value: 1, key: 'test1' });
|
linkedList.appendUnique({ value: 1, key: 'test1' });
|
||||||
linkedList.appendUnique({ value: 2, key: 'test2' });
|
linkedList.appendUnique({ value: 2, key: 'test2' });
|
||||||
linkedList.appendUnique({ value: 3, key: 'test2' });
|
linkedList.appendUnique({ value: 3, key: 'test2' });
|
||||||
|
linkedList.appendUnique({ value: 5, key: 'test1' });
|
||||||
|
|
||||||
expect(linkedList.toString()).toBe('test1:1,test2:3');
|
expect(linkedList.toString()).toBe('test1:5,test2:3');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should find node by its key', () => {
|
it('should find node by its key', () => {
|
||||||
const linkedList = new LinkedList();
|
const linkedList = new LinkedList();
|
||||||
|
|
||||||
|
expect(linkedList.findByKey('test')).toBeNull();
|
||||||
|
|
||||||
linkedList.appendUnique({ value: 1, key: 'test1' });
|
linkedList.appendUnique({ value: 1, key: 'test1' });
|
||||||
linkedList.appendUnique({ value: 2, key: 'test2' });
|
linkedList.appendUnique({ value: 2, key: 'test2' });
|
||||||
linkedList.appendUnique({ value: 3, key: 'test3' });
|
linkedList.appendUnique({ value: 3, key: 'test3' });
|
||||||
|
@ -10,19 +10,19 @@ export default class Queue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
peek() {
|
peek() {
|
||||||
if (!this.linkedList.tail) {
|
if (!this.linkedList.head) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.linkedList.tail.value;
|
return this.linkedList.head.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
add(value) {
|
enqueue(value) {
|
||||||
this.linkedList.append({ value });
|
this.linkedList.append({ value });
|
||||||
}
|
}
|
||||||
|
|
||||||
remove() {
|
dequeue() {
|
||||||
const removedTail = this.linkedList.deleteTail();
|
const removedHead = this.linkedList.deleteHead();
|
||||||
return removedTail ? removedTail.value : null;
|
return removedHead ? removedHead.value : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,2 @@
|
|||||||
# Queue
|
# Queue
|
||||||
|
|
||||||
|Operation |Complexity |
|
|
||||||
|---------------------------|-------------------|
|
|
||||||
|Find |O() |
|
|
||||||
|Insert/delete at beginning |O() |
|
|
||||||
|Insert/delete in middle |O() |
|
|
||||||
|Insert/delete at end |O() |
|
|
||||||
|
@ -7,11 +7,11 @@ describe('Queue', () => {
|
|||||||
expect(queue.linkedList).not.toBeNull();
|
expect(queue.linkedList).not.toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add data to queue', () => {
|
it('should enqueue data to queue', () => {
|
||||||
const queue = new Queue();
|
const queue = new Queue();
|
||||||
|
|
||||||
queue.add(1);
|
queue.enqueue(1);
|
||||||
queue.add(2);
|
queue.enqueue(2);
|
||||||
|
|
||||||
expect(queue.linkedList.toString()).toBe('1,2');
|
expect(queue.linkedList.toString()).toBe('1,2');
|
||||||
});
|
});
|
||||||
@ -21,11 +21,11 @@ describe('Queue', () => {
|
|||||||
|
|
||||||
expect(queue.peek()).toBeNull();
|
expect(queue.peek()).toBeNull();
|
||||||
|
|
||||||
queue.add(1);
|
queue.enqueue(1);
|
||||||
queue.add(2);
|
queue.enqueue(2);
|
||||||
|
|
||||||
expect(queue.peek()).toBe(2);
|
expect(queue.peek()).toBe(1);
|
||||||
expect(queue.peek()).toBe(2);
|
expect(queue.peek()).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should check if queue is empty', () => {
|
it('should check if queue is empty', () => {
|
||||||
@ -33,19 +33,19 @@ describe('Queue', () => {
|
|||||||
|
|
||||||
expect(queue.isEmpty()).toBeTruthy();
|
expect(queue.isEmpty()).toBeTruthy();
|
||||||
|
|
||||||
queue.add(1);
|
queue.enqueue(1);
|
||||||
|
|
||||||
expect(queue.isEmpty()).toBeFalsy();
|
expect(queue.isEmpty()).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should remove from empty', () => {
|
it('should dequeue from queue in FIFO order', () => {
|
||||||
const queue = new Queue();
|
const queue = new Queue();
|
||||||
|
|
||||||
queue.add(1);
|
queue.enqueue(1);
|
||||||
queue.add(2);
|
queue.enqueue(2);
|
||||||
|
|
||||||
expect(queue.remove()).toBe(2);
|
expect(queue.dequeue()).toBe(1);
|
||||||
expect(queue.remove()).toBe(1);
|
expect(queue.dequeue()).toBe(2);
|
||||||
expect(queue.isEmpty()).toBeTruthy();
|
expect(queue.isEmpty()).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
1
src/data-structures/stack/README.md
Normal file
1
src/data-structures/stack/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
# Queue
|
28
src/data-structures/stack/Stack.js
Normal file
28
src/data-structures/stack/Stack.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import LinkedList from '../linked-list/LinkedList';
|
||||||
|
|
||||||
|
export default class Stack {
|
||||||
|
constructor() {
|
||||||
|
this.linkedList = new LinkedList();
|
||||||
|
}
|
||||||
|
|
||||||
|
isEmpty() {
|
||||||
|
return !this.linkedList.tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
peek() {
|
||||||
|
if (!this.linkedList.tail) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.linkedList.tail.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
push(value) {
|
||||||
|
this.linkedList.append({ value });
|
||||||
|
}
|
||||||
|
|
||||||
|
pop() {
|
||||||
|
const removedTail = this.linkedList.deleteTail();
|
||||||
|
return removedTail ? removedTail.value : null;
|
||||||
|
}
|
||||||
|
}
|
51
src/data-structures/stack/__test__/Stack.test.js
Normal file
51
src/data-structures/stack/__test__/Stack.test.js
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import Stack from '../Stack';
|
||||||
|
|
||||||
|
describe('Stack', () => {
|
||||||
|
it('should create empty stack', () => {
|
||||||
|
const stack = new Stack();
|
||||||
|
expect(stack).not.toBeNull();
|
||||||
|
expect(stack.linkedList).not.toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should stack data to stack', () => {
|
||||||
|
const stack = new Stack();
|
||||||
|
|
||||||
|
stack.push(1);
|
||||||
|
stack.push(2);
|
||||||
|
|
||||||
|
expect(stack.linkedList.toString()).toBe('1,2');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should peek data from stack', () => {
|
||||||
|
const stack = new Stack();
|
||||||
|
|
||||||
|
expect(stack.peek()).toBeNull();
|
||||||
|
|
||||||
|
stack.push(1);
|
||||||
|
stack.push(2);
|
||||||
|
|
||||||
|
expect(stack.peek()).toBe(2);
|
||||||
|
expect(stack.peek()).toBe(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check if stack is empty', () => {
|
||||||
|
const stack = new Stack();
|
||||||
|
|
||||||
|
expect(stack.isEmpty()).toBeTruthy();
|
||||||
|
|
||||||
|
stack.push(1);
|
||||||
|
|
||||||
|
expect(stack.isEmpty()).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should pop data from stack', () => {
|
||||||
|
const stack = new Stack();
|
||||||
|
|
||||||
|
stack.push(1);
|
||||||
|
stack.push(2);
|
||||||
|
|
||||||
|
expect(stack.pop()).toBe(2);
|
||||||
|
expect(stack.pop()).toBe(1);
|
||||||
|
expect(stack.isEmpty()).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user