|
|
|
@ -8,15 +8,11 @@ var MergeSort = function() { |
|
|
|
|
|
|
|
|
|
//===== Action management.
|
|
|
|
|
//
|
|
|
|
|
this.reset = function(arr, start, end) { |
|
|
|
|
var len = arr.length; |
|
|
|
|
|
|
|
|
|
this.reset = function(len) { |
|
|
|
|
this |
|
|
|
|
.instruct(Itemgroup.background, 0, 0, '#f00', 0, len) |
|
|
|
|
|
|
|
|
|
.instruct(Itemgroup.opacity, 0, 0, 0, len, 1) |
|
|
|
|
.instruct(Itemgroup.opacity, 0, 0, -1, start - 1, 0.2) |
|
|
|
|
.instruct(Itemgroup.opacity, 0, 0, end + 1, len, 0.2) |
|
|
|
|
|
|
|
|
|
.instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${this.comparisons}`) |
|
|
|
|
.instruct(Itemgroup.message, 0, 0, 2, '') |
|
|
|
@ -25,44 +21,62 @@ var MergeSort = function() { |
|
|
|
|
.instruct(Itemgroup.message, 0, 0, 5, ''); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
this.splitSingle = function(index) { |
|
|
|
|
this |
|
|
|
|
.instruct(Itemgroup.message, 0, 100, 2, `Single element [${index}]`); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
this.preSort = function(start, mid, end) { |
|
|
|
|
this.preSort = function(start, mid, end, len) { |
|
|
|
|
this |
|
|
|
|
.instruct(Itemgroup.message, 0, 0, 2, `Sorting [${start}] - [${end}]`) |
|
|
|
|
.instruct(Itemgroup.message, 0, 0, 3, 'Slicing and recursing:') |
|
|
|
|
.instruct(Itemgroup.message, 0, 100, 4, `[${start}]-[${mid}] and [${mid + 1}]-[${end}]`); |
|
|
|
|
.instruct(Itemgroup.message, 0, 0, 3, 'Slicing and recursing...') |
|
|
|
|
// .instruct(Itemgroup.message, 0, 0, 4, `[${start}]-[${mid}] and [${mid + 1}]-[${end}]`)
|
|
|
|
|
|
|
|
|
|
.instruct(Itemgroup.opacity, 0, 0, -1, start - 1, 0.2) |
|
|
|
|
.instruct(Itemgroup.opacity, 0, 0, end + 1, len, 0.2) |
|
|
|
|
|
|
|
|
|
.instruct(Itemgroup.opacity, 1, 0, 0, len, 0) |
|
|
|
|
.instruct(Itemgroup.opacity, 2, 100, 0, len, 0) |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
this.preMerge = function(start, mid, end, len) { |
|
|
|
|
this.preMerge = function(arr1, arr2, start, mid, end, len) { |
|
|
|
|
var len1 = arr1.length; |
|
|
|
|
var len2 = arr2.length; |
|
|
|
|
|
|
|
|
|
for (var i = 0; i < len1; i++) { |
|
|
|
|
this |
|
|
|
|
.instruct(Itemgroup.text, 1, 0, i, arr1[i]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (var j = 0; j < len2; j++) { |
|
|
|
|
this |
|
|
|
|
.instruct(Itemgroup.text, 1, 0, len1 + j, arr2[j]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
this |
|
|
|
|
.instruct(Itemgroup.message, 0, 0, 2, ``) |
|
|
|
|
.instruct(Itemgroup.message, 0, 0, 3, 'Merging slices:') |
|
|
|
|
.instruct(Itemgroup.message, 0, 0, 4, `[${start}]-[${mid}] and [${mid + 1}]-[${end}]`) |
|
|
|
|
.instruct(Itemgroup.message, 0, 0, 5, '') |
|
|
|
|
|
|
|
|
|
.instruct(Itemgroup.background, 1, 0, 0, len1 - 1, Visualizer.bg1) |
|
|
|
|
.instruct(Itemgroup.background, 1, 0, len1, len1 + len2 - 1, '#751806') |
|
|
|
|
|
|
|
|
|
.instruct(Itemgroup.opacity, 0, 0, 0, len, 0.2) |
|
|
|
|
.instruct(Itemgroup.opacity, 1, 0, 0, len, 0) |
|
|
|
|
.instruct(Itemgroup.opacity, 1, 0, start, end, 1) |
|
|
|
|
.instruct(Itemgroup.opacity, 2, 0, 0, len, 0) |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
this.postMerge = function(len) { |
|
|
|
|
this |
|
|
|
|
.instruct(Itemgroup.opacity, 1, 0, 0, len, 0) |
|
|
|
|
.instruct(Itemgroup.opacity, 1, 100, 0, len1 + len2 - 1, 1) |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
this.midMerge = function(index, value, message) { |
|
|
|
|
this.midMerge = function(indexG1, indexG2, value, message) { |
|
|
|
|
this |
|
|
|
|
.instruct(Itemgroup.opacity, 1, 0, index, index, 1) |
|
|
|
|
.instruct(Itemgroup.text, 1, 0, index, value) |
|
|
|
|
.instruct(Itemgroup.message, 0, 100, 5, `Pushing ${value} to sub-result.`); |
|
|
|
|
.instruct(Itemgroup.opacity, 1, 0, indexG1, indexG1, 0) |
|
|
|
|
|
|
|
|
|
.instruct(Itemgroup.opacity, 2, 0, indexG2, indexG2, 1) |
|
|
|
|
.instruct(Itemgroup.text, 2, 0, indexG2, value) |
|
|
|
|
|
|
|
|
|
.instruct(Itemgroup.message, 0, 0, 4, message) |
|
|
|
|
.instruct(Itemgroup.message, 0, 100, 5, `${value} pushed onto sub-result.`); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
//
|
|
|
|
@ -92,49 +106,37 @@ MergeSort.prototype.init = function() { |
|
|
|
|
.instruct(Itemgroup.foreground, 0, 0, 0, len, Visualizer.fg0) |
|
|
|
|
.instruct(Itemgroup.background, 0, 0, 0, len, Visualizer.bg0) |
|
|
|
|
|
|
|
|
|
.instruct(Itemgroup.opacity, 1, 0, 0, 0, len) |
|
|
|
|
.instruct(Itemgroup.opacity, 1, 0, 0, len, 0) |
|
|
|
|
.instruct(Itemgroup.foreground, 1, 0, 0, len, Visualizer.fg1) |
|
|
|
|
.instruct(Itemgroup.background, 1, 0, 0, len, Visualizer.bg1) |
|
|
|
|
|
|
|
|
|
.instruct(Itemgroup.opacity, 2, 0, 0, 0, len) |
|
|
|
|
.instruct(Itemgroup.opacity, 2, 0, 0, len, 0) |
|
|
|
|
.instruct(Itemgroup.foreground, 2, 0, 0, len, Visualizer.fg2) |
|
|
|
|
.instruct(Itemgroup.background, 2, 100, 0, len, Visualizer.bg2) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this |
|
|
|
|
.instruct(Itemgroup.swap, 0, 1000, 0, 1) |
|
|
|
|
.instruct(Itemgroup.swap, 0, 1000, 1, 2) |
|
|
|
|
.instruct(Itemgroup.swap, 0, 1000, 2, 3) |
|
|
|
|
.instruct(Itemgroup.swap, 0, 1000, 3, 2) |
|
|
|
|
.instruct(Itemgroup.swap, 0, 1000, 2, 1) |
|
|
|
|
.instruct(Itemgroup.swap, 0, 1000, 1, 0) |
|
|
|
|
.instruct(Itemgroup.background, 2, 100, 0, len, Visualizer.bg2); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
MergeSort.prototype.sort = function(arr, start, end) { |
|
|
|
|
this.reset(arr, start, end); |
|
|
|
|
this.reset(arr.length); |
|
|
|
|
|
|
|
|
|
if (arr.length === 0) { |
|
|
|
|
return arr; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (start === end) { |
|
|
|
|
this.splitSingle(start); |
|
|
|
|
return [arr[start]]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var mid = start + Math.floor((end - start) / 2); |
|
|
|
|
|
|
|
|
|
this.preSort(start, mid, end); |
|
|
|
|
this.preSort(start, mid, end, arr.length); |
|
|
|
|
var arr1 = this.sort(arr, start, mid); |
|
|
|
|
var arr2 = this.sort(arr, mid + 1, end); |
|
|
|
|
|
|
|
|
|
this.preMerge(start, mid, end, arr.length); |
|
|
|
|
this.preMerge(arr1, arr2, start, mid, end, arr.length); |
|
|
|
|
var result = this.merge(arr1, arr2); |
|
|
|
|
this.postMerge(arr.length); |
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
|
}; |
|
|
|
@ -146,26 +148,38 @@ MergeSort.prototype.merge = function(arr1, arr2) { |
|
|
|
|
var result = []; |
|
|
|
|
var n; |
|
|
|
|
|
|
|
|
|
// (For reporting only, to keep track of "split" group.)
|
|
|
|
|
var arr1index = 0; |
|
|
|
|
var arr2index = arr1.length; |
|
|
|
|
|
|
|
|
|
while (arr1.length > 0 || arr2.length > 0) { |
|
|
|
|
if (arr1.length === 0) { |
|
|
|
|
n = arr2.shift(); |
|
|
|
|
result.push(n); |
|
|
|
|
this.midMerge(result.length, n, 'One element left to merge.'); |
|
|
|
|
|
|
|
|
|
this.midMerge(arr2index, result.length - 1, n, '(last element)'); |
|
|
|
|
arr2index++; |
|
|
|
|
} |
|
|
|
|
else if (arr2.length === 0) { |
|
|
|
|
n = arr1.shift(); |
|
|
|
|
result.push(n); |
|
|
|
|
this.midMerge(result.length, n, 'One element left to merge.'); |
|
|
|
|
|
|
|
|
|
this.midMerge(arr1index, result.length - 1, n, '(last element)'); |
|
|
|
|
arr1index++; |
|
|
|
|
} |
|
|
|
|
else if (arr1[0] <= arr2[0]) { |
|
|
|
|
n = arr1.shift() |
|
|
|
|
result.push(n); |
|
|
|
|
this.midMerge(result.length, n, `${n} <= ${arr2[0]}`); |
|
|
|
|
|
|
|
|
|
this.midMerge(arr1index, result.length - 1, n, `Compare heads: ${n} <= ${arr2[0]}`); |
|
|
|
|
arr1index++; |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
n = arr2.shift(); |
|
|
|
|
result.push(n); |
|
|
|
|
this.midMerge(result.length, n, `${arr1[0]} > ${n}`); |
|
|
|
|
|
|
|
|
|
this.midMerge(arr2index, result.length - 1, n, `Compare heads: ${arr1[0]} > ${n}`); |
|
|
|
|
arr2index++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
this.comparisons++; |
|
|
|
|