1
+ /**
2
+ * @gaetancovelli /heap
3
+ * Generated by babel.
4
+ * Author: Gaëtan Covelli
5
+ * Last Updated: Wed, 18 Jan 2017 16:06:39 GMT
6
+ */
7
+ "use strict" ;
8
+
9
+ var _createClass = function ( ) { function defineProperties ( target , props ) { for ( var i = 0 ; i < props . length ; i ++ ) { var descriptor = props [ i ] ; descriptor . enumerable = descriptor . enumerable || false ; descriptor . configurable = true ; if ( "value" in descriptor ) descriptor . writable = true ; Object . defineProperty ( target , descriptor . key , descriptor ) ; } } return function ( Constructor , protoProps , staticProps ) { if ( protoProps ) defineProperties ( Constructor . prototype , protoProps ) ; if ( staticProps ) defineProperties ( Constructor , staticProps ) ; return Constructor ; } ; } ( ) ;
10
+
11
+ function _classCallCheck ( instance , Constructor ) { if ( ! ( instance instanceof Constructor ) ) { throw new TypeError ( "Cannot call a class as a function" ) ; } }
12
+
13
+ /**
14
+ * Binary heap implementation in JavaScript ES6.
15
+ * Author: Gaëtan Covelli
16
+ * License: MIT
17
+ *
18
+ * peek() - O(1)
19
+ * pop() - O(log n)
20
+ * push() - O(log n)
21
+ *
22
+ * Usage:
23
+ *
24
+ * new Heap() - Creates an empty min heap
25
+ * new Heap(Heap.MAX_PROPERTY) - Creates an empty max heap
26
+ * new Heap(Heap.MIN_PROPERTY, array) - Creates a min heap from an exsiting array
27
+ * new Heap(Heap.MAX_PROPERTY, array) - Creates a max heap from an exsiting array
28
+ * heap.push(1) - Pushes a number to the heap
29
+ * heap.push([1, 'Task number 1']) - Pushes an array with priority value and a string to track
30
+ * heap.push([1, {name: 'my task'}]) - Pushes an array with priority value and an object to track
31
+ * heap.peek() - Returns the top element of the heap
32
+ * heap.pop() - Pops and returns the top element of the heap
33
+ *
34
+ * This heap implementation uses a 0-based indexing.
35
+ */
36
+ module . exports = function ( ) {
37
+
38
+ /**
39
+ * Creates a new heap.
40
+ *
41
+ * @param {number } property - Optional. The property of the heap.
42
+ * Heap.MIN_PROPERTY (default) or Heap.MAX_PROPERTY.
43
+ * @param {array } array - Optional. An existing array that will get heapified.
44
+ */
45
+ function Heap ( property ) {
46
+ var array = arguments . length > 1 && arguments [ 1 ] !== undefined ? arguments [ 1 ] : [ ] ;
47
+
48
+ _classCallCheck ( this , Heap ) ;
49
+
50
+ this . elements = array ;
51
+ this . property = Heap . MIN_PROPERTY ;
52
+
53
+ if ( property === Heap . MAX_PROPERTY ) {
54
+ this . property = Heap . MAX_PROPERTY ;
55
+ }
56
+
57
+ if ( this . elements . length > 0 ) {
58
+ this . _heapify ( ) ;
59
+ }
60
+ }
61
+
62
+ _createClass ( Heap , [ {
63
+ key : "_getLeftChildIndex" ,
64
+ value : function _getLeftChildIndex ( parentIndex ) {
65
+ return parentIndex * 2 + 1 ;
66
+ }
67
+ } , {
68
+ key : "_getRightChildIndex" ,
69
+ value : function _getRightChildIndex ( parentIndex ) {
70
+ return parentIndex * 2 + 2 ;
71
+ }
72
+ } , {
73
+ key : "_getParentIndex" ,
74
+ value : function _getParentIndex ( childIndex ) {
75
+ return parseInt ( ( childIndex - 1 ) / 2 ) ;
76
+ }
77
+ } , {
78
+ key : "_swap" ,
79
+ value : function _swap ( i , j ) {
80
+ var _ref = [ this . elements [ j ] , this . elements [ i ] ] ;
81
+ this . elements [ i ] = _ref [ 0 ] ;
82
+ this . elements [ j ] = _ref [ 1 ] ;
83
+ }
84
+
85
+ /**
86
+ * Returns the top element of the heap.
87
+ *
88
+ * @return {element } - The element at the top of the heap.
89
+ */
90
+
91
+ } , {
92
+ key : "peek" ,
93
+ value : function peek ( ) {
94
+ return this . elements [ 0 ] ;
95
+ }
96
+
97
+ /**
98
+ * Pops and returns the top element of the heap.
99
+ *
100
+ * @return {element } - The element popped from the top of the heap.
101
+ * It can be a number or an array whose first element is the priority value
102
+ * and second element is the record tracked.
103
+ */
104
+
105
+ } , {
106
+ key : "pop" ,
107
+ value : function pop ( ) {
108
+ var lastValue = this . elements . pop ( ) ;
109
+ var returnVal = lastValue ;
110
+ if ( this . elements . length > 0 ) {
111
+ returnVal = this . elements [ 0 ] ;
112
+ this . elements [ 0 ] = lastValue ;
113
+ this . _heapifyDown ( ) ;
114
+ }
115
+ return returnVal ;
116
+ }
117
+
118
+ /**
119
+ * Pushes a new element to the heap.
120
+ *
121
+ * @param {element } value - The element to be pushed to the heap.
122
+ * It can be a number or an array whose first element is the priority value
123
+ * and second element is the record we want to track.
124
+ *
125
+ * push(1); // A value
126
+ * push([1, 'My task with priority value 1']); // A string
127
+ * push([1, {firstname: 'Gaetan', lastname: 'Covelli'}]); // An object
128
+ */
129
+
130
+ } , {
131
+ key : "push" ,
132
+ value : function push ( value ) {
133
+ this . elements . push ( value ) ;
134
+ if ( this . elements . length > 1 ) {
135
+ this . _heapifyUp ( this . elements . length - 1 ) ;
136
+ }
137
+ }
138
+ } , {
139
+ key : "_heapifyUp" ,
140
+ value : function _heapifyUp ( index ) {
141
+ while ( this . _getParentIndex ( index ) >= 0 ) {
142
+ var swapNeeded = false ;
143
+ var parentIndex = this . _getParentIndex ( index ) ;
144
+
145
+ if ( this . property === Heap . MIN_PROPERTY ) {
146
+ swapNeeded = this . elements [ parentIndex ] > this . elements [ index ] ;
147
+ } else if ( this . property === Heap . MAX_PROPERTY ) {
148
+ swapNeeded = this . elements [ parentIndex ] < this . elements [ index ] ;
149
+ }
150
+
151
+ if ( swapNeeded ) {
152
+ this . _swap ( parentIndex , index ) ;
153
+ index = parentIndex ;
154
+ } else {
155
+ break ;
156
+ }
157
+ }
158
+ }
159
+ } , {
160
+ key : "_heapifyDown" ,
161
+ value : function _heapifyDown ( ) {
162
+ var index = arguments . length > 0 && arguments [ 0 ] !== undefined ? arguments [ 0 ] : 0 ;
163
+
164
+ while ( this . _getLeftChildIndex ( index ) < this . elements . length ) {
165
+ var indexToSwap = this . _getLeftChildIndex ( index ) ;
166
+ var rightChildIndex = this . _getRightChildIndex ( index ) ;
167
+ var isRightChildSwap = false ;
168
+
169
+ if ( this . property === Heap . MIN_PROPERTY ) {
170
+ isRightChildSwap = this . elements [ rightChildIndex ] < this . elements [ indexToSwap ] ;
171
+ } else if ( this . property === Heap . MAX_PROPERTY ) {
172
+ isRightChildSwap = this . elements [ rightChildIndex ] > this . elements [ indexToSwap ] ;
173
+ }
174
+
175
+ if ( rightChildIndex < this . elements . length && isRightChildSwap ) {
176
+ indexToSwap = rightChildIndex ;
177
+ }
178
+
179
+ var swapFinished = false ;
180
+ if ( this . property === Heap . MIN_PROPERTY ) {
181
+ swapFinished = this . elements [ index ] < this . elements [ indexToSwap ] ;
182
+ } else if ( this . property === Heap . MAX_PROPERTY ) {
183
+ swapFinished = this . elements [ index ] > this . elements [ indexToSwap ] ;
184
+ }
185
+
186
+ if ( swapFinished ) {
187
+ break ;
188
+ } else {
189
+ this . _swap ( index , indexToSwap ) ;
190
+ }
191
+ index = indexToSwap ;
192
+ }
193
+ }
194
+
195
+ /**
196
+ * Heapifies an existing array.
197
+ */
198
+
199
+ } , {
200
+ key : "_heapify" ,
201
+ value : function _heapify ( ) {
202
+ for ( var i = parseInt ( this . elements . length / 2 ) ; i >= 0 ; i -- ) {
203
+ this . _heapifyDown ( i ) ;
204
+ }
205
+ }
206
+ } ] , [ {
207
+ key : "MIN_PROPERTY" ,
208
+ get : function get ( ) {
209
+ return 0 ;
210
+ }
211
+ } , {
212
+ key : "MAX_PROPERTY" ,
213
+ get : function get ( ) {
214
+ return 1 ;
215
+ }
216
+ } ] ) ;
217
+
218
+ return Heap ;
219
+ } ( ) ;
0 commit comments