-
Notifications
You must be signed in to change notification settings - Fork 0
/
heap.js
137 lines (136 loc) · 4.17 KB
/
heap.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/**
* This code will hopefully define a fully functional heap
*/
var jfh = jfh || {};
jfh.heap = {};
(function(){
var h = jfh.heap;
/**
* Function to find the parent of a node at possition i
* @param {Number} i the index of the node in the heap
*/
h.parent = function(/*Number*/ i){
return Math.ceil(i/2) - 1;
};
/**
* Function to get the left sub tree of the node at position i
* @param {Number} i the index of the node in the heap
*/
h.left = function(/*Number*/ i){
return (2*(i+1))-1;
};
/**
* Function to get the right sub tree of the node at position i
* @param {Number} i the index of the node in the heap
*/
h.right = function(/*Number*/ i){
return (2*(i+1));
};
/**
* Basic function to make sure the heaps stay in order
* @param {Array} A The array thats holding the information
* @param {Number} i An index into the array
*/
h.maxHeapify = function(/*Array*/ A, /*Number*/ i){
var l = h.left(i);
var r = h.right(i);
var heapSize = A.heapSize;
var largest;
if( l <= heapSize && A[l] > A[i]){
largest = l;
}else{
largest = i;
}
if( r <= heapSize && A[r] > A[largest] ){
largest = r;
}
if( largest != i ){
var tmp = A[i];
A[i] = A[largest];
A[largest] = tmp;
h.maxHeapify(A, largest);
}
};
/**
* Procedure goes throught nodes of the tree and runs maxHeapify on each one
* @param {Array} A the heap to be
*/
h.buildMaxHeap = function(/*Array*/ A){
var heapSize = A.length - 1;
A.heapSize = heapSize;
for(var i = Math.floor(heapSize/2); i >= 0 ; i--){
// This is the textbook implementation, but maybe I should figure
// out how to implement this so that it's indexed from 0...
h.maxHeapify(A,i);
}
};
/**
* The algorithm to actually sort an array using heaps
* @param {Array} A the array to be sorted
*/
h.heapsort = function(/*Array*/ A){
h.buildMaxHeap(A);
var len = A.length - 1;
for(var i = len; i >= 1; i--){
// Exchange 1 and i... this isn't confusing at all...
var tmp = A[i];
A[i] = A[0];
A[0] = tmp;
A.heapSize = A.heapSize - 1;
h.maxHeapify(A, 0);
}
};
/**
* The function to get the max element in the heap runs in constant time
* obviously
* @param {Array} A the heap to extract the max element from
*/
h.heapMaximum = function(/*Array*/ A){
// This implementation is indexed from 0
return A[0];
};
/**
* The point of this functino is to actually remove the max element from
* the heap. So if you are using it like a queue of some kind you can
* easily pop off elements
* @param {Array} A the heap
*/
h.extractMax = function(/*Array*/ A){
if(A.heapSize < 0){
return Error('Heap Underflow');
}
var max = h.heapMaximum(A);
A[0] = A[A.heapSize];
A.heapSize = A.heapSize - 1;
h.maxHeapify(A,0);
return max;
};
/**
* The increase key function. Could be used for a queue as well
* @param {Array} A the heap
* @param {Number} i the index of the element whose key we are increasing
* @param {Number} key the key actual key
*/
h.increaseKey = function(/*Array*/ A, /*Number*/ i, /*Number*/ key){
if( key < A[i]){
return Error('New Key is smaller than current key');
}
A[i] = key;
while(i > 0 && A[h.parent(i)] < A[i]){
var tmp = A[i];
A[i] = A[h.parent(i)];
A[h.parent(i)] = tmp;
i = h.parent(i);
}
};
/**
* Inserts the given key into the heap
* @param {Array} A The heap
* @param {Number} key The key to be inserted
*/
h.heapInsert = function(/*Array*/ A, /*Number*/ key){
A.heapSize = A.heapSize + 1;
A[A.heapSize] = -Infinity;
h.increaseKey(A, A.heapSize, key);
};
})();