Skip to content

Commit 55df4d0

Browse files
authored
Merge pull request knaxus#156 from knaxus/heaps
Heaps
2 parents a7956bd + 2c1011a commit 55df4d0

File tree

10 files changed

+222
-22
lines changed

10 files changed

+222
-22
lines changed

.assets/dsa.jpeg

94.8 KB
Loading

.assets/logo.png

9.5 KB
Loading

README.md

+13-8
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
<img src=".assets/logo.png" align="right"/>
2+
13
# Problem Solving using Javascript
24

35
[![Open Source Love](https://badges.frapsoft.com/os/v2/open-source.svg?v=103)](https://github.com/vinitshahdeo/HacktoberFest)
@@ -7,17 +9,20 @@
79

810
Collection of interview questions with Unit Tests. Problems includes Data Structures, Logical and few Classical problems.
911

10-
## Table of Contents
12+
![DSA](.assets/dsa.jpeg)
13+
14+
## Overview
15+
16+
This repo contains the following sections implemented in **JavaScript**
1117

12-
This repo contains the following in **JavaScript**
13-
- Data Structures
14-
- Algorithms
15-
- Logical Problems
16-
- Classics (Few of the classical questions)
18+
- [Data Structures](src/_DataStructures_)
19+
- [Algorithms](src/_Algorithms_)
20+
- [Logical Problems](src/_Problems_)
21+
- [Classics (Few of the classical questions)](src/_Classics_)
1722

18-
Find the detailed Table of Contents here: [Detailed TOC](TOC.md)
23+
Find the detailed contents and problem list here: [Table Of Contents](TOC.md)
1924

20-
## CONTRIBUTION Guide
25+
## Contribution Guide
2126

2227
It's great to know that you want to contribute to this repo. Thanks for taking interest. please fing the [guide here](https://github.com/knaxus/problem-solving-javascript/blob/master/CONTRIBUTING.md)
2328

TOC.md

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
## Table of Contents
32

43
### Data Structures
@@ -44,6 +43,12 @@
4443
- [Unique words count in a Trie](src/_DataStructures_/Trees/Trie/unique-word-count)
4544
- [All the words from a Trie](src/_DataStructures_/Trees/Trie/all-words-in-trie)
4645
- [Unique words in a Trie](src/_DataStructures_/Trees/Trie/get-unique-words)
46+
- [Heaps](src/_DataStructures_/Heaps)
47+
- [MaxHeap](src/_DataStructures_/Heaps/MaxHeap)
48+
- [MinHeap](src/_DataStructures_/Heaps/MinHeap)
49+
- Problems
50+
- [K Largest Elements](src/_DataStructures_/Heaps/k-largest-in-array)
51+
- [K Smallest Elements](src/_DataStructures_/Heaps/k-smallest-in-array)
4752

4853
### Logical Problems
4954

@@ -75,8 +80,7 @@
7580

7681
- [LRU Cache](src/_Algorithms_/lru-cache)
7782
- Path Finders
78-
- [A*](src/_Algorithms_/path-finder/a-star)
79-
83+
- [A\*](src/_Algorithms_/path-finder/a-star)
8084

8185
### Classics
8286

src/_DataStructures_/Heaps/MaxHeap/MaxHeap.test.js

+9
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ describe('MaxHeap', () => {
1515
expect(mh instanceof MaxHeap).toEqual(true);
1616
});
1717

18+
it('Should create a MaxHeap using collection', () => {
19+
const mHBulk = new MaxHeap([1, 3, 21, 9, 101, 0]);
20+
expect(mHBulk.getMax()).toEqual(101);
21+
});
22+
1823
it('Should add an element to the MaxHeap', () => {
1924
mh.add(10);
2025
expect(mh.getMax()).toEqual(10);
@@ -47,4 +52,8 @@ describe('MaxHeap', () => {
4752
expect(mh.remove()).toEqual(1);
4853
expect(mh.getMax()).toEqual(null);
4954
});
55+
56+
it('Should return `null` on `remove() called on empty heap`', () => {
57+
expect(mh.getMax()).toEqual(null);
58+
});
5059
});

src/_DataStructures_/Heaps/MaxHeap/index.js

+13-11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
class MaxHeap {
2-
constructor() {
2+
constructor(collection) {
33
this.heap = [];
4+
if (collection) {
5+
collection.forEach((element) => {
6+
this.add(element);
7+
});
8+
}
49
}
510

611
add(element) {
@@ -11,27 +16,24 @@ class MaxHeap {
1116
}
1217

1318
getMax() {
14-
return this.heap[0] || null;
19+
return this.heap[0] !== undefined ? this.heap[0] : null;
1520
}
1621

1722
remove() {
23+
const max = this.heap[0] !== undefined ? this.heap[0] : null;
1824
// return the element at the root
19-
const max = this.heap[0] || null;
25+
if (this.heap.length === 1) {
26+
this.heap.pop();
27+
}
28+
2029
if (this.heap.length > 1) {
2130
// move the leaf to the root
2231
this.heap[0] = this.heap[this.heap.length - 1];
23-
this.heap.splice(this.heap.length - 1, 1);
32+
this.heap.pop();
2433
// restore the heapify property
2534
// eslint-disable-next-line no-underscore-dangle
2635
this.__heapify(0);
27-
return max;
2836
}
29-
30-
if (this.heap.length === 1) {
31-
this.heap.splice(this.heap.length - 1, 1);
32-
return max;
33-
}
34-
3537
return max;
3638
}
3739

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
const MinHeap = require('.');
2+
3+
describe('MinHeap', () => {
4+
it('Should be a class', () => {
5+
expect(typeof MinHeap.prototype.constructor).toEqual('function');
6+
});
7+
8+
const mh = new MinHeap();
9+
10+
beforeEach(() => {
11+
mh.destroy();
12+
});
13+
14+
it('Should create an instance of MinHeap', () => {
15+
expect(mh instanceof MinHeap).toEqual(true);
16+
});
17+
18+
it('Should create a MinHeap using collection', () => {
19+
const mHBulk = new MinHeap([112, 3, 21, 9, 10, 0]);
20+
expect(mHBulk.getMin()).toEqual(0);
21+
});
22+
23+
it('Should add an element to the MinHeap', () => {
24+
mh.add(10);
25+
expect(mh.getMin()).toEqual(10);
26+
});
27+
28+
it('Should keep the smallest element at the root', () => {
29+
[12, 5, 34].forEach(el => mh.add(el));
30+
expect(mh.getMin()).toEqual(5);
31+
});
32+
33+
it('Should retain Heap properties after removal of an element', () => {
34+
[12, 45, 1, 34].forEach(el => mh.add(el));
35+
expect(mh.getMin()).toEqual(1);
36+
mh.remove();
37+
expect(mh.getMin()).toEqual(12);
38+
});
39+
40+
it('Should return `null` when heap is empty', () => {
41+
[1, 34].forEach(el => mh.add(el));
42+
expect(mh.getMin()).toEqual(1);
43+
mh.remove();
44+
mh.remove();
45+
expect(mh.getMin()).toEqual(null);
46+
});
47+
48+
it('Should return the elelment value on `remove()`', () => {
49+
[1, 34].forEach(el => mh.add(el));
50+
expect(mh.getMin()).toEqual(1);
51+
expect(mh.remove()).toEqual(1);
52+
expect(mh.remove()).toEqual(34);
53+
expect(mh.getMin()).toEqual(null);
54+
});
55+
56+
it('Should return `null` on `remove() called on empty heap`', () => {
57+
expect(mh.getMin()).toEqual(null);
58+
});
59+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
class MinHeap {
2+
constructor(collection) {
3+
this.heap = [];
4+
5+
if (collection) {
6+
collection.forEach((element) => {
7+
this.add(element);
8+
});
9+
}
10+
}
11+
12+
add(element) {
13+
this.heap.push(element);
14+
// check for the parent element & swap if required
15+
// eslint-disable-next-line no-underscore-dangle
16+
this.__traverseUpAndSwap(this.heap.length - 1);
17+
}
18+
19+
getMin() {
20+
return this.heap[0] !== undefined ? this.heap[0] : null;
21+
}
22+
23+
remove() {
24+
const min = this.heap[0] !== undefined ? this.heap[0] : null;
25+
if (this.heap.length === 1) {
26+
this.heap.pop();
27+
}
28+
if (this.heap.length > 1) {
29+
this.heap[0] = this.heap[this.heap.length - 1];
30+
this.heap.pop();
31+
// eslint-disable-next-line no-underscore-dangle
32+
this.__heapify(0);
33+
}
34+
return min;
35+
}
36+
37+
destroy() {
38+
this.heap = [];
39+
}
40+
41+
// eslint-disable-next-line consistent-return
42+
__traverseUpAndSwap(index) {
43+
if (index <= 0) return null;
44+
45+
const parent = Math.floor(index / 2);
46+
47+
if (this.heap[parent] > this.heap[index]) {
48+
const temp = this.heap[parent];
49+
this.heap[parent] = this.heap[index];
50+
this.heap[index] = temp;
51+
// eslint-disable-next-line no-underscore-dangle
52+
this.__traverseUpAndSwap(parent);
53+
}
54+
}
55+
56+
__heapify(index) {
57+
const left = index * 2;
58+
const right = index * 2 + 1;
59+
60+
let smallest = index;
61+
62+
if (this.heap.length > left && this.heap[smallest] > this.heap[left]) {
63+
smallest = left;
64+
}
65+
if (this.heap.length > right && this.heap[smallest] > this.heap[right]) {
66+
smallest = right;
67+
}
68+
if (smallest !== index) {
69+
const tmp = this.heap[smallest];
70+
this.heap[smallest] = this.heap[index];
71+
this.heap[index] = tmp;
72+
// eslint-disable-next-line no-underscore-dangle
73+
this.__heapify(smallest);
74+
}
75+
}
76+
}
77+
78+
module.exports = MinHeap;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
const MaxHeap = require('../MaxHeap');
2+
3+
/**
4+
* Find the 4 largest elements from an array
5+
*/
6+
7+
function findKLargest(collection, k) {
8+
if (!collection || !Array.isArray(collection)) {
9+
throw new Error('Invalid / missing collection');
10+
}
11+
12+
// create a MaxHeap using the collection
13+
const mh = new MaxHeap(collection);
14+
const result = [];
15+
16+
for (let i = 0; i < k; i += 1) {
17+
result.push(mh.remove());
18+
}
19+
return result;
20+
}
21+
22+
module.exports = findKLargest;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* Find 4 smallest elements in an array
3+
*/
4+
5+
const MinHeap = require('../MinHeap');
6+
7+
function findKSmallest(collection, k) {
8+
if (!collection || !Array.isArray(collection)) {
9+
throw new Error('Invalid / missing collection');
10+
}
11+
12+
// create a MinHeap using the collection
13+
const mh = new MinHeap(collection);
14+
const result = [];
15+
for (let i = 0; i < k; i += 1) {
16+
result.push(mh.remove());
17+
}
18+
return result;
19+
}
20+
21+
module.exports = findKSmallest;

0 commit comments

Comments
 (0)