1
+ // Heapsort animation
2
+ //
3
+ // It's worth looking at this code if you are planning to write any new
4
+ // modules.
5
+ //
6
+ // This was the first animation done and the code is reasonably simple -
7
+ // the abstractions supported match what we need for this algorithm.
8
+ // For various other algorithms, the code seems much more messy - maybe
9
+ // the abstractions for the data structures/rendering are not quite what
10
+ // is needed or the coding is done with a sledgehammer, so to speak.
11
+ //
12
+ // The original version of this code was not quite right in the way it
13
+ // adapted (or didn't adapt) to expansion/collapse of code blocks. This
14
+ // was added later in a reasonably simple way (again, other algorithms
15
+ // may use the sledgehammer style).
16
+ //
17
+ // One thing that could make the code here more readable is to use
18
+ // meaningful strings for bookmarks rather than numbers.
19
+
1
20
/* eslint-disable no-multi-spaces,indent,prefer-destructuring,brace-style */
2
21
import GraphTracer from '../../components/DataStructures/Graph/GraphTracer' ;
3
22
import ArrayTracer from '../../components/DataStructures/Array/Array1DTracer' ;
4
23
import { areExpanded } from './collapseChunkPlugin' ;
5
24
6
25
// k displayed only if first BuildHeap is expanded
26
+ // Note: This is only needed in the last chunk of BuildHeap. The code
27
+ // looks like it displays k throughout BuildHeap but when BuildHeap is
28
+ // collapsed, only the last chunk is rendered so the other chunks don't
29
+ // matter and we can avoid testing what is expanded there. Another
30
+ // approach would be to use a wrapper function for assigning to k, which
31
+ // checks isBuildHeapExpanded() (it doesn't generalise well for i and j
32
+ // though).
7
33
function isBuildHeapExpanded ( ) {
8
34
return areExpanded ( [ 'BuildHeap' ] ) ;
9
35
}
10
36
11
37
// i, j (in build) displayed only if first DownHeap is expanded
38
+ // See Note in isBuildHeapExpanded()
12
39
function isDownHeapkExpanded ( ) {
13
40
return areExpanded ( [ 'BuildHeap' , 'DownHeapk' ] ) ;
14
41
}
15
42
16
- // i, j (in sort) displayed only if second DownHeap is expanded
17
- function isDownHeap1Expanded ( ) {
18
- return areExpanded ( [ 'SortHeap' , 'DownHeap1' ] ) ;
19
- }
20
-
21
43
export default {
22
44
initVisualisers ( ) {
23
45
return {
@@ -85,22 +107,21 @@ export default {
85
107
} , [ n1 , n2 ] ) ;
86
108
} ;
87
109
88
- /** NOTE: In Linda 's code, array index starts from 1
110
+ /** NOTE: In Lee 's code, array index starts from 1
89
111
* however, in JS, array index naturally starts from 0
90
112
* index start from 0:
91
113
* parent = k , left child = 2*k + 1, right child = 2*k + 2
92
114
* index start from 1:
93
115
* parent = k , left child = 2*k, right child = 2*k + 1
94
116
*/
95
117
96
- let lastiHighlight = null ;
118
+ // keep track of last node highlighted due to i (or k) so we can
119
+ // unhighlight it of buildHeap is collapsed
120
+ let lastiHighlight ;
97
121
98
122
// build heap
99
123
// start from the last non-leaf node, work backwards to maintain the heap
100
124
for ( let k = Math . floor ( n / 2 ) - 1 ; k >= 0 ; k -= 1 ) {
101
- // chunker.add(4, (vis, index) => {
102
- // vis.array.assignVariable('k', index);
103
- // }, [k]);
104
125
105
126
let j ;
106
127
const tmp = i ;
@@ -117,12 +138,6 @@ export default {
117
138
} , [ i , tmp ] ) ;
118
139
119
140
chunker . add ( 6 , ( vis , index1 , index2 ) => {
120
- // if (tmp != null) { // XXX looks dodgy using tmp here?
121
- // if (index2 != null) {
122
- // unhighlight(vis, index2);
123
- // vis.array.removeVariable('j');
124
- // }
125
- // highlight(vis, index1);
126
141
vis . array . assignVariable ( 'i' , index1 ) ;
127
142
} , [ i , tmp ] ) ;
128
143
@@ -160,15 +175,13 @@ export default {
160
175
// possible last chunk in BuildHeap/DownHeapk
161
176
// remove i, j if !isDownHeapkExpanded
162
177
if ( ! isDownHeapkExpanded ( ) ) {
163
- vis . array . assignVariable ( 'i' , undefined ) ;
164
- vis . array . assignVariable ( 'j' , undefined ) ;
178
+ vis . array . removeVariable ( 'i' ) ;
179
+ vis . array . removeVariable ( 'j' ) ;
165
180
}
166
181
// remove k+highlighting if !isBuildHeapExpanded
167
182
if ( ! isBuildHeapExpanded ( ) ) {
168
- vis . array . assignVariable ( 'k' , undefined ) ;
169
- if ( lastiHighlight !== null ) {
170
- unhighlight ( vis , lastH ) ;
171
- }
183
+ vis . array . removeVariable ( 'k' ) ;
184
+ unhighlight ( vis , lastH ) ;
172
185
}
173
186
} , [ j , lastiHighlight ] ) ;
174
187
} else {
@@ -182,15 +195,13 @@ export default {
182
195
vis . array . assignVariable ( 'i' , c ) ;
183
196
// remove i, j if !isDownHeapkExpanded
184
197
if ( ! isDownHeapkExpanded ( ) ) {
185
- vis . array . assignVariable ( 'i' , undefined ) ;
186
- vis . array . assignVariable ( 'j' , undefined ) ;
198
+ vis . array . removeVariable ( 'i' ) ;
199
+ vis . array . removeVariable ( 'j' ) ;
187
200
}
188
201
// remove k+highlighting if !isDownHeapkExpanded
189
202
if ( ! isBuildHeapExpanded ( ) ) {
190
- vis . array . assignVariable ( 'k' , undefined ) ;
191
- if ( lastiHighlight !== null ) {
192
- unhighlight ( vis , lastH ) ;
193
- }
203
+ vis . array . removeVariable ( 'k' ) ;
204
+ unhighlight ( vis , lastH ) ;
194
205
}
195
206
} , [ i , j , lastiHighlight ] ) ;
196
207
i = j ;
@@ -202,18 +213,10 @@ export default {
202
213
203
214
while ( n > 1 ) {
204
215
chunker . add ( 20 , ( vis , nVal , index ) => {
205
- // if first iteration of while loop - clear variables & show 'n'
206
- if ( nVal === nodes . length ) {
207
- vis . array . clearVariables ( ) ;
208
- vis . array . assignVariable ( 'n' , nVal - 1 ) ;
209
- } else {
210
- vis . array . removeVariable ( 'i' ) ;
211
- vis . array . removeVariable ( 'j' ) ;
212
- }
213
-
214
- // else only clear 'j'
215
-
216
- unhighlight ( vis , index ) ;
216
+ // clear variables & show 'n'
217
+ vis . array . clearVariables ( ) ;
218
+ vis . array . assignVariable ( 'n' , nVal - 1 ) ;
219
+ unhighlight ( vis , index ) ; // XXX skip for first loop iteration?
217
220
} , [ n , i ] ) ;
218
221
219
222
let j ;
@@ -228,7 +231,6 @@ export default {
228
231
swapAction ( 21 , 0 , n - 1 ) ;
229
232
230
233
chunker . add ( 22 , ( vis , index ) => {
231
- // unhighlight(vis, index);
232
234
unhighlight ( vis , index , false ) ;
233
235
vis . array . sorted ( index ) ;
234
236
vis . heap . sorted ( index + 1 ) ;
@@ -239,17 +241,14 @@ export default {
239
241
240
242
i = 0 ;
241
243
chunker . add ( 24 , ( vis , index1 , nVal ) => {
242
- if ( nVal > 0 ) {
243
- // highlight(vis, index1);
244
- }
245
244
vis . array . assignVariable ( 'i' , index1 ) ;
246
245
} , [ i , n ] ) ;
247
246
248
247
chunker . add ( 25 ) ;
249
248
heap = false ;
250
249
251
250
chunker . add ( 26 , ( vis , nVal ) => {
252
- if ( nVal === 0 ) vis . array . clearVariables ( ) ;
251
+ // if (nVal === 0) vis.array.clearVariables();
253
252
} , [ n ] ) ;
254
253
// need to maintain the heap after swap
255
254
while ( ! ( 2 * i + 1 >= n || heap ) ) {
@@ -274,12 +273,6 @@ export default {
274
273
heap = true ;
275
274
chunker . add ( 33 , ( vis , index ) => {
276
275
unhighlight ( vis , index , false ) ;
277
- // possible last chunk in SortHeap/DownHeap1
278
- // remove i, j if !isDownHeap1Expanded
279
- if ( ! isDownHeap1Expanded ( ) ) {
280
- vis . array . assignVariable ( 'i' , undefined ) ;
281
- vis . array . assignVariable ( 'j' , undefined ) ;
282
- }
283
276
} , [ j ] ) ;
284
277
} else {
285
278
swap = A [ i ] ;
@@ -289,12 +282,6 @@ export default {
289
282
chunker . add ( 36 , ( vis , p , c ) => {
290
283
unhighlight ( vis , p , false ) ;
291
284
vis . array . assignVariable ( 'i' , c ) ;
292
- // possible last chunk in SortHeap/DownHeap1
293
- // remove i, j if !isDownHeap1Expanded
294
- if ( ! isDownHeap1Expanded ( ) ) {
295
- vis . array . assignVariable ( 'i' , undefined ) ;
296
- vis . array . assignVariable ( 'j' , undefined ) ;
297
- }
298
285
} , [ i , j ] ) ;
299
286
i = j ;
300
287
}
0 commit comments