1
- // Merge sort for lists (represented using array), top down
2
- // Prototype for pointer version. Adapted code from array version.
3
- // XXX Could do with a good clean up!
4
- // Lots of crud - may include some quicksort remnants also; probably
5
- // should have cleaned up mergesort array code before copying it...
6
- // Uses simple stack display like DFSrec
1
+ // This comment is entirely for the
2
+ // amusement of the person who wrote
3
+ // it and should be ignored by anyone
4
+ // else. However, THE COMMENTS BELOW
5
+ // SHOULD BE READ BY ANYONE LOOKING
6
+ // AT THE CODE, PARTICULARLY IF IT IS
7
+ // TO BE MODIFIED!
8
+
9
+ // Animation of merge sort for lists (represented using array), top down.
10
+ // XXX PROTOTYPE for pointer version. Adapted from code for mergesort for
11
+ // arrays (may include some quicksort remnants also).
12
+ // XXX Needs major clean up of code to remove junk, refactor, etc before
13
+ // being used for anything else
14
+ // XXX Not all steps are animated
15
+ // XXX should be more consistent with mergesort for arrays with colours
16
+ // etc
17
+ // XXX Colours are very limited - colour support is a mystery to me and
18
+ // there are major inconsistencies between colours specification for
19
+ // graph nodes/edges, 1D arrays and 2D arrays (there is a student group
20
+ // that will hopefully look into this and improve things)
7
21
8
22
import { msort_lista_td } from '../explanations' ;
9
23
@@ -155,7 +169,8 @@ const unhighlightB = (vis, index, isPrimaryColor = true) => {
155
169
export function initVisualisers ( ) {
156
170
return {
157
171
array : {
158
- instance : new Array2DTracer ( 'array' , null , 'Array representation of lists' ) ,
172
+ instance : new Array2DTracer ( 'array' , null ,
173
+ 'Array representation of lists (PROTOTYPE FOR POINTER REPRESENTATION)' ) ,
159
174
order : 0 ,
160
175
} ,
161
176
}
@@ -184,6 +199,14 @@ export function run_msort() {
184
199
// Define helper functions
185
200
// ----------------------------------------------------------------------------------------------------------------------------
186
201
202
+ function assignMaybeNullVar ( vis , variable_name , index ) {
203
+ if ( index === 'Null' ) {
204
+ vis . array . assignVariable ( variable_name , 2 , undefined ) ;
205
+ vis . array . assignVariable ( variable_name + '=Null' , 2 , 0 ) ;
206
+ } else
207
+ vis . array . assignVariable ( variable_name , 2 , index ) ;
208
+ }
209
+
187
210
function assignVarToA ( vis , variable_name , index ) {
188
211
if ( index === undefined )
189
212
vis . array . removeVariable ( variable_name ) ;
@@ -247,7 +270,13 @@ export function run_msort() {
247
270
248
271
chunker . add ( 'Main' , ( vis , Lists , cur_L , cur_len , cur_depth , c_stk ) => {
249
272
vis . array . set ( Lists , 'msort_lista_td' ) ;
250
- vis . array . assignVariable ( 'L' , 2 , cur_L ) ;
273
+ vis . array . assignVariable ( 'L' , 2 , cur_L ) ;
274
+ // colour all of R list
275
+ let Tails = Lists [ 2 ] ;
276
+ for ( let i = cur_L ; i !== 'Null' ; i = Tails [ i ] ) {
277
+ vis . array . select ( 1 , i , 1 , i , '0' ) ;
278
+ vis . array . select ( 2 , i , 2 , i , '0' ) ;
279
+ }
251
280
// if (cur_depth === 0) {
252
281
// }
253
282
// for (let i = cur_left; i <= cur_right; i++) {
@@ -289,17 +318,22 @@ cur_R, c_stk) => {
289
318
vis . array . assignVariable ( 'L' , 2 , cur_L ) ;
290
319
vis . array . assignVariable ( 'Mid' , 2 , cur_Mid ) ;
291
320
vis . array . assignVariable ( 'R' , 2 , cur_R ) ;
321
+ vis . array . select ( 1 , cur_L , 1 , cur_L , '0' ) ;
322
+ vis . array . select ( 2 , cur_L , 2 , cur_L , '0' ) ;
323
+ vis . array . select ( 1 , cur_R , 1 , cur_R , '0' ) ;
324
+ vis . array . select ( 2 , cur_R , 2 , cur_R , '0' ) ;
292
325
} , [ [ Indices , Heads , Tails ] , L , Mid , R , simple_stack ] , depth ) ;
293
326
294
327
// dummy chunk for before recursive call - we need this so there
295
328
// is a chunk at this recursion level as the first chunk in the
296
329
// collapsed code for the recursive call
297
- chunker . add ( 'preSortL' , ( vis , Lists , cur_L , cur_Mid , cur_R ) => {
298
- // vis.array.set(Lists, 'msort_lista_td');
299
- // set_simple_stack(vis.array, c_stk);
300
- vis . array . assignVariable ( 'Mid' , 2 , undefined ) ;
301
- vis . array . assignVariable ( 'R' , 2 , undefined ) ;
302
- } , [ [ Indices , Heads , Tails ] , L , Mid , R ] , depth ) ;
330
+ chunker . add ( 'preSortL' , ( vis , Lists , cur_L , cur_Mid , cur_R , c_stk ) => {
331
+ vis . array . set ( Lists , 'msort_lista_td' ) ;
332
+ set_simple_stack ( vis . array , c_stk ) ;
333
+ vis . array . assignVariable ( 'L' , 2 , cur_L ) ;
334
+ vis . array . select ( 1 , cur_L , 1 , cur_L , '0' ) ;
335
+ vis . array . select ( 2 , cur_L , 2 , cur_L , '0' ) ;
336
+ } , [ [ Indices , Heads , Tails ] , L , Mid , R , simple_stack ] , depth ) ;
303
337
304
338
305
339
L = MergeSort ( L , midNum , depth + 1 ) ;
@@ -312,6 +346,14 @@ cur_R, c_stk) => {
312
346
set_simple_stack ( vis . array , c_stk ) ;
313
347
vis . array . assignVariable ( 'L' , 2 , cur_L ) ;
314
348
vis . array . assignVariable ( 'R' , 2 , cur_R ) ;
349
+ // colour all of L list
350
+ let Tails = Lists [ 2 ] ;
351
+ for ( let i = cur_L ; i !== 'Null' ; i = Tails [ i ] ) {
352
+ vis . array . select ( 1 , i , 1 , i , '1' ) ;
353
+ vis . array . select ( 2 , i , 2 , i , '1' ) ;
354
+ }
355
+ vis . array . select ( 1 , cur_R , 1 , cur_R , '0' ) ;
356
+ vis . array . select ( 2 , cur_R , 2 , cur_R , '0' ) ;
315
357
// for (let i = cur_left; i <= cur_mid; i++) {
316
358
// unhighlight(vis, i, true);
317
359
// highlight(vis, i, false)
@@ -322,14 +364,20 @@ cur_R, c_stk) => {
322
364
} , [ [ Indices , Heads , Tails ] , L , R , Mid , simple_stack ] , depth ) ;
323
365
324
366
// dummy chunk before recursive call, as above
325
- chunker . add ( 'preSortR' , ( vis , a , cur_L , cur_Mid , cur_R ) => {
326
- // vis.array.set(a, 'msort_lista_td');
327
- // for (let i = cur_left; i <= cur_mid; i++) {
328
- // unhighlight(vis, i, false);
329
- // }
330
- vis . array . assignVariable ( 'L' , 2 , undefined ) ;
367
+ chunker . add ( 'preSortR' , ( vis , Lists , cur_L , cur_Mid , cur_R , c_stk ) => {
368
+ vis . array . set ( Lists , 'msort_lista_td' ) ;
369
+ set_simple_stack ( vis . array , c_stk ) ;
370
+ // vis.array.assignVariable('L', 2, undefined);
331
371
vis . array . assignVariable ( 'R' , 2 , cur_R ) ;
332
- } , [ [ Indices , Heads , Tails ] , L , Mid , R ] , depth ) ;
372
+ vis . array . select ( 1 , cur_R , 1 , cur_R , '0' ) ;
373
+ vis . array . select ( 2 , cur_R , 2 , cur_R , '0' ) ;
374
+ // colour all of R list
375
+ // let Tails = Lists[2];
376
+ // for (let i = cur_R; i !== 'Null'; i = Tails[i]) {
377
+ // vis.array.select(1, i, 1, i, '1');
378
+ // vis.array.select(2, i, 2, i, '1');
379
+ // }
380
+ } , [ [ Indices , Heads , Tails ] , L , Mid , R , simple_stack ] , depth ) ;
333
381
334
382
R = MergeSort ( R , len - midNum , depth + 1 ) ;
335
383
@@ -341,6 +389,15 @@ c_stk) => {
341
389
set_simple_stack ( vis . array , c_stk ) ;
342
390
vis . array . assignVariable ( 'L' , 2 , cur_L ) ;
343
391
vis . array . assignVariable ( 'R' , 2 , cur_R ) ;
392
+ vis . array . select ( 1 , cur_L , 1 , cur_L , '0' ) ;
393
+ vis . array . select ( 2 , cur_L , 2 , cur_L , '0' ) ;
394
+ // colour all of R list
395
+ let Tails = Lists [ 2 ] ;
396
+ for ( let i = cur_R ; i !== 'Null' ; i = Tails [ i ] ) {
397
+ vis . array . select ( 1 , i , 1 , i , '1' ) ;
398
+ vis . array . select ( 2 , i , 2 , i , '1' ) ;
399
+ }
400
+
344
401
// for (let i = cur_mid+1; i <= cur_right; i++) {
345
402
// unhighlight(vis, i, true);
346
403
// unhighlight(vis, i, false)
@@ -358,28 +415,160 @@ c_stk) => {
358
415
}
359
416
// scan through adding elements to the end of M
360
417
let E = M ;
418
+ chunker . add ( 'E' , ( vis , Lists , cur_L , cur_R , cur_M , cur_E , c_stk ) => {
419
+ vis . array . set ( Lists , 'msort_lista_td' ) ;
420
+ set_simple_stack ( vis . array , c_stk ) ;
421
+ assignMaybeNullVar ( vis , 'L' , cur_L ) ;
422
+ assignMaybeNullVar ( vis , 'R' , cur_R ) ;
423
+ vis . array . assignVariable ( 'M' , 2 , cur_M ) ;
424
+ vis . array . assignVariable ( 'E' , 2 , cur_E ) ;
425
+ if ( cur_L !== 'Null' ) {
426
+ vis . array . select ( 1 , cur_L , 1 , cur_L , '0' ) ;
427
+ vis . array . select ( 2 , cur_L , 2 , cur_L , '0' ) ;
428
+ }
429
+ if ( cur_R !== 'Null' ) {
430
+ vis . array . select ( 1 , cur_R , 1 , cur_R , '0' ) ;
431
+ vis . array . select ( 2 , cur_R , 2 , cur_R , '0' ) ;
432
+ }
433
+ vis . array . select ( 1 , cur_M , 1 , cur_M , '1' ) ;
434
+ vis . array . select ( 2 , cur_M , 2 , cur_M , '1' ) ;
435
+ } , [ [ Indices , Heads , Tails ] , L , R , M , E , simple_stack ] , depth ) ;
361
436
while ( L !== 'Null' && R !== 'Null' ) {
362
- if ( Heads [ L ] <= Heads [ R ] ) {
363
- Tails [ E ] = L ;
364
- E = L ;
365
- L = Tails [ L ] ;
366
- } else {
367
- Tails [ E ] = R ;
368
- E = R ;
369
- R = Tails [ R ] ;
437
+ chunker . add ( 'whileNotNull' , ( vis , Lists , cur_L , cur_R , cur_M , cur_E , c_stk ) => {
438
+ vis . array . set ( Lists , 'msort_lista_td' ) ;
439
+ set_simple_stack ( vis . array , c_stk ) ;
440
+ assignMaybeNullVar ( vis , 'L' , cur_L ) ;
441
+ assignMaybeNullVar ( vis , 'R' , cur_R ) ;
442
+ vis . array . assignVariable ( 'M' , 2 , cur_M ) ;
443
+ assignMaybeNullVar ( vis , 'E' , cur_E ) ;
444
+ if ( cur_L !== 'Null' ) {
445
+ vis . array . select ( 1 , cur_L , 1 , cur_L , '0' ) ;
446
+ vis . array . select ( 2 , cur_L , 2 , cur_L , '0' ) ;
447
+ }
448
+ if ( cur_R !== 'Null' ) {
449
+ vis . array . select ( 1 , cur_R , 1 , cur_R , '0' ) ;
450
+ vis . array . select ( 2 , cur_R , 2 , cur_R , '0' ) ;
370
451
}
452
+ // colour all of M list, up to + including cur_E
453
+ // (we don't color up to Null because the tail of E hasn't
454
+ // been smashed)
455
+ let Tails = Lists [ 2 ] ;
456
+ for ( let i = cur_M ; i !== cur_E ; i = Tails [ i ] ) {
457
+ vis . array . select ( 1 , i , 1 , i , '1' ) ;
458
+ vis . array . select ( 2 , i , 2 , i , '1' ) ;
459
+ }
460
+ if ( cur_E !== 'Null' ) {
461
+ vis . array . select ( 1 , cur_E , 1 , cur_E , '1' ) ;
462
+ vis . array . select ( 2 , cur_E , 2 , cur_E , '1' ) ;
463
+ }
464
+ } , [ [ Indices , Heads , Tails ] , L , R , M , E , simple_stack ] , depth ) ;
465
+ if ( Heads [ L ] <= Heads [ R ] ) {
466
+ Tails [ E ] = L ;
467
+ E = L ;
468
+ L = Tails [ L ] ;
469
+ chunker . add ( 'popL' , ( vis , Lists , cur_L , cur_R , cur_M , cur_E , c_stk ) => {
470
+ vis . array . set ( Lists , 'msort_lista_td' ) ;
471
+ set_simple_stack ( vis . array , c_stk ) ;
472
+ assignMaybeNullVar ( vis , 'L' , cur_L ) ;
473
+ assignMaybeNullVar ( vis , 'R' , cur_R ) ;
474
+ vis . array . assignVariable ( 'M' , 2 , cur_M ) ;
475
+ assignMaybeNullVar ( vis , 'E' , cur_E ) ;
476
+ if ( cur_L !== 'Null' ) {
477
+ vis . array . select ( 1 , cur_L , 1 , cur_L , '0' ) ;
478
+ vis . array . select ( 2 , cur_L , 2 , cur_L , '0' ) ;
479
+ }
480
+ if ( cur_R !== 'Null' ) {
481
+ vis . array . select ( 1 , cur_R , 1 , cur_R , '0' ) ;
482
+ vis . array . select ( 2 , cur_R , 2 , cur_R , '0' ) ;
483
+ }
484
+ // colour all of M list, up to + including cur_E
485
+ // (we don't color up to Null because the tail of E hasn't
486
+ // been smashed)
487
+ let Tails = Lists [ 2 ] ;
488
+ for ( let i = cur_M ; i !== cur_E ; i = Tails [ i ] ) {
489
+ vis . array . select ( 1 , i , 1 , i , '1' ) ;
490
+ vis . array . select ( 2 , i , 2 , i , '1' ) ;
491
+ }
492
+ if ( cur_E !== 'Null' ) {
493
+ vis . array . select ( 1 , cur_E , 1 , cur_E , '1' ) ;
494
+ vis . array . select ( 2 , cur_E , 2 , cur_E , '1' ) ;
495
+ }
496
+ } , [ [ Indices , Heads , Tails ] , L , R , M , E , simple_stack ] , depth ) ;
497
+ } else {
498
+ Tails [ E ] = R ;
499
+ E = R ;
500
+ R = Tails [ R ] ;
501
+ chunker . add ( 'popR' , ( vis , Lists , cur_L , cur_R , cur_M , cur_E , c_stk ) => {
502
+ vis . array . set ( Lists , 'msort_lista_td' ) ;
503
+ set_simple_stack ( vis . array , c_stk ) ;
504
+ assignMaybeNullVar ( vis , 'L' , cur_L ) ;
505
+ assignMaybeNullVar ( vis , 'R' , cur_R ) ;
506
+ vis . array . assignVariable ( 'M' , 2 , cur_M ) ;
507
+ assignMaybeNullVar ( vis , 'E' , cur_E ) ;
508
+ if ( cur_L !== 'Null' ) {
509
+ vis . array . select ( 1 , cur_L , 1 , cur_L , '0' ) ;
510
+ vis . array . select ( 2 , cur_L , 2 , cur_L , '0' ) ;
511
+ }
512
+ if ( cur_R !== 'Null' ) {
513
+ vis . array . select ( 1 , cur_R , 1 , cur_R , '0' ) ;
514
+ vis . array . select ( 2 , cur_R , 2 , cur_R , '0' ) ;
515
+ }
516
+ // colour all of M list, up to + including cur_E
517
+ // (we don't color up to Null because the tail of E hasn't
518
+ // been smashed)
519
+ let Tails = Lists [ 2 ] ;
520
+ for ( let i = cur_M ; i !== cur_E ; i = Tails [ i ] ) {
521
+ vis . array . select ( 1 , i , 1 , i , '1' ) ;
522
+ vis . array . select ( 2 , i , 2 , i , '1' ) ;
523
+ }
524
+ if ( cur_E !== 'Null' ) {
525
+ vis . array . select ( 1 , cur_E , 1 , cur_E , '1' ) ;
526
+ vis . array . select ( 2 , cur_E , 2 , cur_E , '1' ) ;
527
+ }
528
+ } , [ [ Indices , Heads , Tails ] , L , R , M , E , simple_stack ] , depth ) ;
529
+ }
371
530
}
372
531
// add any elements not scanned to the end of M
373
- if ( L === 'Null' )
374
- Tails [ E ] = R ;
375
- else
376
- Tails [ E ] = L ;
532
+ if ( L === 'Null' ) {
533
+ Tails [ E ] = R ;
534
+ chunker . add ( 'appendR' , ( vis , Lists , cur_L , cur_R , cur_M , cur_E , c_stk ) => {
535
+ vis . array . set ( Lists , 'msort_lista_td' ) ;
536
+ set_simple_stack ( vis . array , c_stk ) ;
537
+ vis . array . assignVariable ( 'M' , 2 , cur_M ) ;
538
+ // colour all of M list
539
+ let Tails = Lists [ 2 ] ;
540
+ for ( let i = cur_M ; i !== 'Null' ; i = Tails [ i ] ) {
541
+ vis . array . select ( 1 , i , 1 , i , '1' ) ;
542
+ vis . array . select ( 2 , i , 2 , i , '1' ) ;
543
+ }
544
+ } , [ [ Indices , Heads , Tails ] , L , R , M , E , simple_stack ] , depth ) ;
545
+ } else {
546
+ Tails [ E ] = L ;
547
+ chunker . add ( 'appendL' , ( vis , Lists , cur_L , cur_R , cur_M , cur_E , c_stk ) => {
548
+ vis . array . set ( Lists , 'msort_lista_td' ) ;
549
+ set_simple_stack ( vis . array , c_stk ) ;
550
+ vis . array . assignVariable ( 'M' , 2 , cur_M ) ;
551
+ // colour all of M list
552
+ let Tails = Lists [ 2 ] ;
553
+ for ( let i = cur_M ; i !== 'Null' ; i = Tails [ i ] ) {
554
+ vis . array . select ( 1 , i , 1 , i , '1' ) ;
555
+ vis . array . select ( 2 , i , 2 , i , '1' ) ;
556
+ }
557
+ } , [ [ Indices , Heads , Tails ] , L , R , M , E , simple_stack ] , depth ) ;
558
+ }
377
559
chunker . add ( 'returnM' , ( vis , Lists , cur_L , cur_M , c_stk ) => {
378
560
vis . array . set ( Lists , 'msort_lista_td' ) ;
379
561
set_simple_stack ( vis . array , c_stk ) ;
380
562
vis . array . assignVariable ( 'L' , 2 , undefined ) ;
381
563
vis . array . assignVariable ( 'R' , 2 , undefined ) ;
564
+ vis . array . assignVariable ( 'E' , 2 , undefined ) ;
382
565
vis . array . assignVariable ( 'M' , 2 , cur_M ) ;
566
+ // colour all of M list
567
+ let Tails = Lists [ 2 ] ;
568
+ for ( let i = cur_M ; i !== 'Null' ; i = Tails [ i ] ) {
569
+ vis . array . select ( 1 , i , 1 , i , '1' ) ;
570
+ vis . array . select ( 2 , i , 2 , i , '1' ) ;
571
+ }
383
572
} , [ [ Indices , Heads , Tails ] , L , M , simple_stack ] , depth ) ;
384
573
385
574
@@ -597,6 +786,8 @@ cur_right, c_stk) => {
597
786
else
598
787
{
599
788
chunker . add ( 'returnL' , ( vis , a , cur_L ) => {
789
+ vis . array . select ( 1 , cur_L , 1 , cur_L , '1' ) ;
790
+ vis . array . select ( 2 , cur_L , 2 , cur_L , '1' ) ;
600
791
// if (cur_left === cur_right) {
601
792
// unhighlight(vis, cur_left, true);
602
793
// highlight(vis, cur_left, false)
0 commit comments