mirror of
https://github.moeyy.xyz/https://github.com/trekhleb/javascript-algorithms.git
synced 2024-12-26 07:01:18 +08:00
Add Stack.
This commit is contained in:
parent
159d489e52
commit
8da6754523
@ -4,9 +4,9 @@
|
||||
|
||||
## Data Structures
|
||||
|
||||
- [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)
|
||||
- [Queue](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/queue)
|
||||
1. [Linked List](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/linked-list)
|
||||
2. [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
|
||||
|
||||
|
@ -160,6 +160,23 @@ export default class LinkedList {
|
||||
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) {
|
||||
let currentNode = this.head;
|
||||
|
||||
|
@ -43,6 +43,8 @@ describe('LinkedList', () => {
|
||||
it('should delete node by value from linked list', () => {
|
||||
const linkedList = new LinkedList();
|
||||
|
||||
expect(linkedList.deleteByValue(5)).toBeNull();
|
||||
|
||||
linkedList.append({ value: 1 });
|
||||
linkedList.append({ value: 2 });
|
||||
linkedList.append({ value: 3 });
|
||||
@ -80,55 +82,103 @@ describe('LinkedList', () => {
|
||||
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', () => {
|
||||
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: 2 });
|
||||
|
||||
expect(linkedList.head.toString()).toBe('1');
|
||||
expect(linkedList.tail.toString()).toBe('2');
|
||||
|
||||
const deletedNode1 = linkedList.deleteTail();
|
||||
const deletedNode1 = linkedList.deleteHead();
|
||||
|
||||
expect(deletedNode1.value).toBe(2);
|
||||
expect(linkedList.toString()).toBe('1');
|
||||
expect(linkedList.head.toString()).toBe('1');
|
||||
expect(linkedList.tail.toString()).toBe('1');
|
||||
expect(deletedNode1.value).toBe(1);
|
||||
expect(linkedList.toString()).toBe('2');
|
||||
expect(linkedList.head.toString()).toBe('2');
|
||||
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.head).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', () => {
|
||||
const linkedList = new LinkedList();
|
||||
|
||||
linkedList.appendUnique({ value: 1, key: 'test1' });
|
||||
linkedList.appendUnique({ value: 2, 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', () => {
|
||||
const linkedList = new LinkedList();
|
||||
|
||||
expect(linkedList.findByKey('test')).toBeNull();
|
||||
|
||||
linkedList.appendUnique({ value: 1, key: 'test1' });
|
||||
linkedList.appendUnique({ value: 2, key: 'test2' });
|
||||
linkedList.appendUnique({ value: 3, key: 'test3' });
|
||||
|
@ -10,19 +10,19 @@ export default class Queue {
|
||||
}
|
||||
|
||||
peek() {
|
||||
if (!this.linkedList.tail) {
|
||||
if (!this.linkedList.head) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.linkedList.tail.value;
|
||||
return this.linkedList.head.value;
|
||||
}
|
||||
|
||||
add(value) {
|
||||
enqueue(value) {
|
||||
this.linkedList.append({ value });
|
||||
}
|
||||
|
||||
remove() {
|
||||
const removedTail = this.linkedList.deleteTail();
|
||||
return removedTail ? removedTail.value : null;
|
||||
dequeue() {
|
||||
const removedHead = this.linkedList.deleteHead();
|
||||
return removedHead ? removedHead.value : null;
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,2 @@
|
||||
# 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();
|
||||
});
|
||||
|
||||
it('should add data to queue', () => {
|
||||
it('should enqueue data to queue', () => {
|
||||
const queue = new Queue();
|
||||
|
||||
queue.add(1);
|
||||
queue.add(2);
|
||||
queue.enqueue(1);
|
||||
queue.enqueue(2);
|
||||
|
||||
expect(queue.linkedList.toString()).toBe('1,2');
|
||||
});
|
||||
@ -21,11 +21,11 @@ describe('Queue', () => {
|
||||
|
||||
expect(queue.peek()).toBeNull();
|
||||
|
||||
queue.add(1);
|
||||
queue.add(2);
|
||||
queue.enqueue(1);
|
||||
queue.enqueue(2);
|
||||
|
||||
expect(queue.peek()).toBe(2);
|
||||
expect(queue.peek()).toBe(2);
|
||||
expect(queue.peek()).toBe(1);
|
||||
expect(queue.peek()).toBe(1);
|
||||
});
|
||||
|
||||
it('should check if queue is empty', () => {
|
||||
@ -33,19 +33,19 @@ describe('Queue', () => {
|
||||
|
||||
expect(queue.isEmpty()).toBeTruthy();
|
||||
|
||||
queue.add(1);
|
||||
queue.enqueue(1);
|
||||
|
||||
expect(queue.isEmpty()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should remove from empty', () => {
|
||||
it('should dequeue from queue in FIFO order', () => {
|
||||
const queue = new Queue();
|
||||
|
||||
queue.add(1);
|
||||
queue.add(2);
|
||||
queue.enqueue(1);
|
||||
queue.enqueue(2);
|
||||
|
||||
expect(queue.remove()).toBe(2);
|
||||
expect(queue.remove()).toBe(1);
|
||||
expect(queue.dequeue()).toBe(1);
|
||||
expect(queue.dequeue()).toBe(2);
|
||||
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