Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit a02d5f6

Browse files
committed
Move common Max/Min Heap code to Heap.js.
1 parent 031c5da commit a02d5f6

File tree

3 files changed

+126
-182
lines changed

3 files changed

+126
-182
lines changed

‎src/data-structures/heap/Heap.js‎

Lines changed: 108 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,52 @@ export default class Heap {
142142
return this;
143143
}
144144

145+
/**
146+
* @param {*} item
147+
* @param {Comparator} [customFindingComparator]
148+
* @return {Heap}
149+
*/
150+
remove(item, customFindingComparator) {
151+
// Find number of items to remove.
152+
const customComparator = customFindingComparator || this.compare;
153+
const numberOfItemsToRemove = this.find(item, customComparator).length;
154+
155+
for (let iteration = 0; iteration < numberOfItemsToRemove; iteration += 1) {
156+
// We need to find item index to remove each time after removal since
157+
// indices are being change after each heapify process.
158+
const indexToRemove = this.find(item, customComparator).pop();
159+
160+
// If we need to remove last child in the heap then just remove it.
161+
// There is no need to heapify the heap afterwards.
162+
if (indexToRemove === (this.heapContainer.length - 1)) {
163+
this.heapContainer.pop();
164+
} else {
165+
// Move last element in heap to the vacant (removed) position.
166+
this.heapContainer[indexToRemove] = this.heapContainer.pop();
167+
168+
// Get parent.
169+
const parentItem = this.hasParent(indexToRemove) ? this.parent(indexToRemove) : null;
170+
const leftChild = this.hasLeftChild(indexToRemove) ? this.leftChild(indexToRemove) : null;
171+
172+
// If there is no parent or parent is in incorrect order with the node
173+
// we're going to delete then heapify down. Otherwise heapify up.
174+
if (
175+
leftChild !== null
176+
&& (
177+
parentItem === null
178+
|| !this.pairIsInCorrectOrder(parentItem, this.heapContainer[indexToRemove])
179+
)
180+
) {
181+
this.heapifyDown(indexToRemove);
182+
} else {
183+
this.heapifyUp(indexToRemove);
184+
}
185+
}
186+
}
187+
188+
return this;
189+
}
190+
145191
/**
146192
* @param {*} item
147193
* @param {Comparator} [customComparator]
@@ -174,11 +220,69 @@ export default class Heap {
174220
return this.heapContainer.toString();
175221
}
176222

177-
heapifyUp() {
178-
throw new Error('You have to implement this method!');
223+
/**
224+
* @param {number} [customStartIndex]
225+
*/
226+
heapifyUp(customStartIndex) {
227+
// Take last element (last in array or the bottom left in a tree) in
228+
// a heap container and lift him up until we find the parent element
229+
// that is less then the current new one.
230+
let currentIndex = customStartIndex || this.heapContainer.length - 1;
231+
232+
while (
233+
this.hasParent(currentIndex)
234+
&& !this.pairIsInCorrectOrder(this.parent(currentIndex), this.heapContainer[currentIndex])
235+
) {
236+
this.swap(currentIndex, this.getParentIndex(currentIndex));
237+
currentIndex = this.getParentIndex(currentIndex);
238+
}
179239
}
180240

181-
heapifyDown() {
182-
throw new Error('You have to implement this method!');
241+
/**
242+
* @param {number} [customStartIndex]
243+
*/
244+
heapifyDown(customStartIndex) {
245+
// Compare the root element to its children and swap root with the smallest
246+
// of children. Do the same for next children after swap.
247+
let currentIndex = customStartIndex || 0;
248+
let nextIndex = null;
249+
250+
while (this.hasLeftChild(currentIndex)) {
251+
if (
252+
this.hasRightChild(currentIndex)
253+
&& this.pairIsInCorrectOrder(this.rightChild(currentIndex), this.leftChild(currentIndex))
254+
) {
255+
nextIndex = this.getRightChildIndex(currentIndex);
256+
} else {
257+
nextIndex = this.getLeftChildIndex(currentIndex);
258+
}
259+
260+
if (!this.pairIsInCorrectOrder(
261+
this.heapContainer[nextIndex],
262+
this.heapContainer[currentIndex],
263+
)) {
264+
break;
265+
}
266+
267+
this.swap(currentIndex, nextIndex);
268+
currentIndex = nextIndex;
269+
}
270+
}
271+
272+
/**
273+
* Checks if pair of heap elements is in correct order.
274+
* For MinHeap the first element must be always smaller or equal.
275+
* For MaxHeap the first element must be always bigger or equal.
276+
*
277+
* @param {*} firstElement
278+
* @param {*} secondElement
279+
* @return {boolean}
280+
*/
281+
/* istanbul ignore next */
282+
pairIsInCorrectOrder(firstElement, secondElement) {
283+
throw new Error(`
284+
You have to implement heap pair comparision method
285+
for ${firstElement} and ${secondElement} values.
286+
`);
183287
}
184288
}

‎src/data-structures/heap/MaxHeap.js‎

Lines changed: 9 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -2,96 +2,15 @@ import Heap from './Heap';
22

33
export default class MaxHeap extends Heap {
44
/**
5-
* @param {*} item
6-
* @param {Comparator} [customFindingComparator]
7-
* @return {MaxHeap}
5+
* Checks if pair of heap elements is in correct order.
6+
* For MinHeap the first element must be always smaller or equal.
7+
* For MaxHeap the first element must be always bigger or equal.
8+
*
9+
* @param {*} firstElement
10+
* @param {*} secondElement
11+
* @return {boolean}
812
*/
9-
remove(item, customFindingComparator) {
10-
// Find number of items to remove.
11-
const customComparator = customFindingComparator || this.compare;
12-
const numberOfItemsToRemove = this.find(item, customComparator).length;
13-
14-
for (let iteration = 0; iteration < numberOfItemsToRemove; iteration += 1) {
15-
// We need to find item index to remove each time after removal since
16-
// indices are being change after each heapify process.
17-
const indexToRemove = this.find(item, customComparator).pop();
18-
19-
// If we need to remove last child in the heap then just remove it.
20-
// There is no need to heapify the heap afterwards.
21-
if (indexToRemove === (this.heapContainer.length - 1)) {
22-
this.heapContainer.pop();
23-
} else {
24-
// Move last element in heap to the vacant (removed) position.
25-
this.heapContainer[indexToRemove] = this.heapContainer.pop();
26-
27-
// Get parent.
28-
const parentItem = this.hasParent(indexToRemove) ? this.parent(indexToRemove) : null;
29-
const leftChild = this.hasLeftChild(indexToRemove) ? this.leftChild(indexToRemove) : null;
30-
31-
// If there is no parent or parent is greater then node to delete then heapify down.
32-
// Otherwise heapify up.
33-
if (
34-
leftChild !== null
35-
&& (
36-
parentItem === null
37-
|| this.compare.greaterThan(parentItem, this.heapContainer[indexToRemove])
38-
)
39-
) {
40-
this.heapifyDown(indexToRemove);
41-
} else {
42-
this.heapifyUp(indexToRemove);
43-
}
44-
}
45-
}
46-
47-
return this;
48-
}
49-
50-
/**
51-
* @param {number} [customStartIndex]
52-
*/
53-
heapifyUp(customStartIndex) {
54-
// Take last element (last in array or the bottom left in a tree) in
55-
// a heap container and lift him up until we find the parent element
56-
// that is greater then the current new one.
57-
let currentIndex = customStartIndex || this.heapContainer.length - 1;
58-
59-
while (
60-
this.hasParent(currentIndex)
61-
&& this.compare.greaterThan(this.heapContainer[currentIndex], this.parent(currentIndex))
62-
) {
63-
this.swap(currentIndex, this.getParentIndex(currentIndex));
64-
currentIndex = this.getParentIndex(currentIndex);
65-
}
66-
}
67-
68-
/**
69-
* @param {number} [customStartIndex]
70-
*/
71-
heapifyDown(customStartIndex) {
72-
// Compare the root element to its children and swap root with the biggest
73-
// of children. Do the same for next children after swap.
74-
let currentIndex = customStartIndex || 0;
75-
let nextIndex = null;
76-
77-
while (this.hasLeftChild(currentIndex)) {
78-
if (
79-
this.hasRightChild(currentIndex)
80-
&& this.compare.greaterThan(this.rightChild(currentIndex), this.leftChild(currentIndex))
81-
) {
82-
nextIndex = this.getRightChildIndex(currentIndex);
83-
} else {
84-
nextIndex = this.getLeftChildIndex(currentIndex);
85-
}
86-
87-
if (
88-
this.compare.greaterThan(this.heapContainer[currentIndex], this.heapContainer[nextIndex])
89-
) {
90-
break;
91-
}
92-
93-
this.swap(currentIndex, nextIndex);
94-
currentIndex = nextIndex;
95-
}
13+
pairIsInCorrectOrder(firstElement, secondElement) {
14+
return this.compare.greaterThanOrEqual(firstElement, secondElement);
9615
}
9716
}

‎src/data-structures/heap/MinHeap.js‎

Lines changed: 9 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -2,94 +2,15 @@ import Heap from './Heap';
22

33
export default class MinHeap extends Heap {
44
/**
5-
* @param {*} item
6-
* @param {Comparator} [customFindingComparator]
7-
* @return {MinHeap}
5+
* Checks if pair of heap elements is in correct order.
6+
* For MinHeap the first element must be always smaller or equal.
7+
* For MaxHeap the first element must be always bigger or equal.
8+
*
9+
* @param {*} firstElement
10+
* @param {*} secondElement
11+
* @return {boolean}
812
*/
9-
remove(item, customFindingComparator) {
10-
// Find number of items to remove.
11-
const customComparator = customFindingComparator || this.compare;
12-
const numberOfItemsToRemove = this.find(item, customComparator).length;
13-
14-
for (let iteration = 0; iteration < numberOfItemsToRemove; iteration += 1) {
15-
// We need to find item index to remove each time after removal since
16-
// indices are being change after each heapify process.
17-
const indexToRemove = this.find(item, customComparator).pop();
18-
19-
// If we need to remove last child in the heap then just remove it.
20-
// There is no need to heapify the heap afterwards.
21-
if (indexToRemove === (this.heapContainer.length - 1)) {
22-
this.heapContainer.pop();
23-
} else {
24-
// Move last element in heap to the vacant (removed) position.
25-
this.heapContainer[indexToRemove] = this.heapContainer.pop();
26-
27-
// Get parent.
28-
const parentItem = this.hasParent(indexToRemove) ? this.parent(indexToRemove) : null;
29-
const leftChild = this.hasLeftChild(indexToRemove) ? this.leftChild(indexToRemove) : null;
30-
31-
// If there is no parent or parent is less then node to delete then heapify down.
32-
// Otherwise heapify up.
33-
if (
34-
leftChild !== null
35-
&& (
36-
parentItem === null
37-
|| this.compare.lessThan(parentItem, this.heapContainer[indexToRemove])
38-
)
39-
) {
40-
this.heapifyDown(indexToRemove);
41-
} else {
42-
this.heapifyUp(indexToRemove);
43-
}
44-
}
45-
}
46-
47-
return this;
48-
}
49-
50-
/**
51-
* @param {number} [customStartIndex]
52-
*/
53-
heapifyUp(customStartIndex) {
54-
// Take last element (last in array or the bottom left in a tree) in
55-
// a heap container and lift him up until we find the parent element
56-
// that is less then the current new one.
57-
let currentIndex = customStartIndex || this.heapContainer.length - 1;
58-
59-
while (
60-
this.hasParent(currentIndex)
61-
&& this.compare.lessThan(this.heapContainer[currentIndex], this.parent(currentIndex))
62-
) {
63-
this.swap(currentIndex, this.getParentIndex(currentIndex));
64-
currentIndex = this.getParentIndex(currentIndex);
65-
}
66-
}
67-
68-
/**
69-
* @param {number} [customStartIndex]
70-
*/
71-
heapifyDown(customStartIndex) {
72-
// Compare the root element to its children and swap root with the smallest
73-
// of children. Do the same for next children after swap.
74-
let currentIndex = customStartIndex || 0;
75-
let nextIndex = null;
76-
77-
while (this.hasLeftChild(currentIndex)) {
78-
if (
79-
this.hasRightChild(currentIndex)
80-
&& this.compare.lessThan(this.rightChild(currentIndex), this.leftChild(currentIndex))
81-
) {
82-
nextIndex = this.getRightChildIndex(currentIndex);
83-
} else {
84-
nextIndex = this.getLeftChildIndex(currentIndex);
85-
}
86-
87-
if (this.compare.lessThan(this.heapContainer[currentIndex], this.heapContainer[nextIndex])) {
88-
break;
89-
}
90-
91-
this.swap(currentIndex, nextIndex);
92-
currentIndex = nextIndex;
93-
}
13+
pairIsInCorrectOrder(firstElement, secondElement) {
14+
return this.compare.lessThanOrEqual(firstElement, secondElement);
9415
}
9516
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /