|
|
|
@ -2,8 +2,86 @@ |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
var MergeSort = function(VisualizerInstance) { |
|
|
|
|
//===== Inits.
|
|
|
|
|
this.V = VisualizerInstance; |
|
|
|
|
this.comparisons = 0; |
|
|
|
|
|
|
|
|
|
//===== Action management.
|
|
|
|
|
//
|
|
|
|
|
this.initSort = function(arr, start, end) { |
|
|
|
|
this.V |
|
|
|
|
.instruct(this.V.unhighlight, 0) |
|
|
|
|
.instruct(this.V.unfade, 0) |
|
|
|
|
.instruct(this.V.fade, 0, -1, start - 1) |
|
|
|
|
.instruct(this.V.fade, 0, end + 1, arr.length) |
|
|
|
|
.instruct(this.V.message, 0, 1, `Comparisons: ${this.comparisons}`) |
|
|
|
|
.instruct(this.V.message, 0, 2, '') |
|
|
|
|
.instruct(this.V.message, 0, 3, '') |
|
|
|
|
.instruct(this.V.message, 0, 4, '') |
|
|
|
|
.instruct(this.V.message, 0, 5, ''); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
this.splitSingle = function(index) { |
|
|
|
|
this.V.instruct(this.V.message, 100, 2, `Single element [${index}]`); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
this.preSort = function(start, mid, end) { |
|
|
|
|
this.V |
|
|
|
|
.instruct(this.V.message, 0, 2, `Sorting [${start}] - [${end}]`) |
|
|
|
|
.instruct(this.V.message, 0, 3, 'Slicing and recursing:') |
|
|
|
|
.instruct(this.V.message, 100, 4, `[${start}]-[${mid}] and [${mid + 1}]-[${end}]`); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
this.preMerge = function(arr1, arr2, start, mid, end) { |
|
|
|
|
var i, j, x, y, v; |
|
|
|
|
var len1 = arr1.length; |
|
|
|
|
var len2 = arr2.length; |
|
|
|
|
|
|
|
|
|
for (var i = 0; i < len1; i++) { |
|
|
|
|
x = Visualizer.padding + (i + start) * (Visualizer.itemW + Visualizer.spacerW); |
|
|
|
|
y = Visualizer.padding * 2 + Visualizer.itemH; |
|
|
|
|
v = arr1[i].value; |
|
|
|
|
this.V.instruct(this.V.item, 0, 'secondary', x, y, v, '#05350D') |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (var j = 0; j < len2; j++) { |
|
|
|
|
x = Visualizer.padding + (j + len1 + start) * (Visualizer.itemW + Visualizer.spacerW); |
|
|
|
|
y = Visualizer.padding * 2 + Visualizer.itemH; |
|
|
|
|
v = arr2[j].value; |
|
|
|
|
this.V.instruct(this.V.item, 0, 'secondary', x, y, v, '#028E2D') |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
this.V |
|
|
|
|
// .instruct(this.V.fade, 0, 0, arr.length)
|
|
|
|
|
.instruct(this.V.message, 0, 2, ``) |
|
|
|
|
.instruct(this.V.message, 0, 3, 'Merging slices:') |
|
|
|
|
.instruct(this.V.message, 0, 4, `[${start}]-[${mid}] and [${mid + 1}]-[${end}]`) |
|
|
|
|
.instruct(this.V.removeTertiary, 0); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
this.postMerge = function() { |
|
|
|
|
this.V.instruct(this.V.removeSecondary, 0); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
this.midMerge = function(index, value, message) { |
|
|
|
|
var x = Visualizer.padding + index * (Visualizer.itemW + Visualizer.spacerW); |
|
|
|
|
var y = Visualizer.padding * 3 + Visualizer.itemH * 2 |
|
|
|
|
|
|
|
|
|
this.V |
|
|
|
|
.instruct(this.V.item, 0, 'tertiary', x, y, value, '#8E5500') |
|
|
|
|
.instruct(this.V.message, 0, 4, message) |
|
|
|
|
.instruct(this.V.message, 100, 5, `Pushing ${value} to sub-result.`); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
this.updateComparisons = function() { |
|
|
|
|
this.V.instruct(this.V.message, 0, 1, `Comparisons: ${this.comparisons}`); |
|
|
|
|
}; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
MergeSort.prototype = Object.create(Sorter.prototype); |
|
|
|
@ -12,64 +90,28 @@ MergeSort.prototype = Object.create(Sorter.prototype); |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
MergeSort.prototype.sort = function(arr, start, end) { |
|
|
|
|
this.V |
|
|
|
|
.instruct(this.V.unhighlight, 0) |
|
|
|
|
.instruct(this.V.unfade, 0) |
|
|
|
|
.instruct(this.V.fade, 0, -1, start - 1) |
|
|
|
|
.instruct(this.V.fade, 0, end + 1, arr.length) |
|
|
|
|
.instruct(this.V.message, 0, 1, `Comparisons: ${this.comparisons}`) |
|
|
|
|
.instruct(this.V.message, 0, 2, '') |
|
|
|
|
.instruct(this.V.message, 0, 3, '') |
|
|
|
|
.instruct(this.V.message, 0, 4, '') |
|
|
|
|
.instruct(this.V.message, 0, 5, ''); |
|
|
|
|
this.initSort(arr, start, end); |
|
|
|
|
|
|
|
|
|
if (arr.length === 0) { |
|
|
|
|
return arr; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (start === end) { |
|
|
|
|
this.V |
|
|
|
|
.instruct(this.V.message, 100, 2, `Single element [${start}]`) |
|
|
|
|
this.splitSingle(start); |
|
|
|
|
return new Array(arr[start]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var mid = start + Math.floor((end - start) / 2); |
|
|
|
|
|
|
|
|
|
this.V |
|
|
|
|
.instruct(this.V.message, 0, 2, `Sorting [${start}] - [${end}]`) |
|
|
|
|
.instruct(this.V.message, 0, 3, 'Slicing and recursing:') |
|
|
|
|
.instruct(this.V.message, 100, 4, `[${start}]-[${mid}] and [${mid + 1}]-[${end}]`); |
|
|
|
|
|
|
|
|
|
this.preSort(start, mid, end); |
|
|
|
|
var arr1 = this.sort(arr, start, mid); |
|
|
|
|
var arr2 = this.sort(arr, mid + 1, end); |
|
|
|
|
|
|
|
|
|
var i, j, x, y, v; |
|
|
|
|
var len1 = arr1.length; |
|
|
|
|
var len2 = arr2.length; |
|
|
|
|
|
|
|
|
|
for (var i = 0; i < len1; i++) { |
|
|
|
|
x = Visualizer.padding + (i + start) * (Visualizer.itemW + Visualizer.spacerW); |
|
|
|
|
y = Visualizer.padding * 2 + Visualizer.itemH; |
|
|
|
|
v = arr1[i].value; |
|
|
|
|
this.V.instruct(this.V.item, 0, 'secondary', x, y, v, '#05350D') |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (var j = 0; j < len2; j++) { |
|
|
|
|
x = Visualizer.padding + (j + len1 + start) * (Visualizer.itemW + Visualizer.spacerW); |
|
|
|
|
y = Visualizer.padding * 2 + Visualizer.itemH; |
|
|
|
|
v = arr2[j].value; |
|
|
|
|
this.V.instruct(this.V.item, 0, 'secondary', x, y, v, '#028E2D') |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
this.V |
|
|
|
|
.instruct(this.V.fade, 0, 0, arr.length) |
|
|
|
|
.instruct(this.V.message, 0, 2, ``) |
|
|
|
|
.instruct(this.V.message, 0, 3, 'Merging slices:') |
|
|
|
|
.instruct(this.V.message, 0, 4, `[${start}]-[${mid}] and [${mid + 1}]-[${end}]`) |
|
|
|
|
|
|
|
|
|
this.preMerge(arr1, arr2, start, mid, end); |
|
|
|
|
var result = this.merge(arr1, arr2); |
|
|
|
|
this.V.instruct(this.V.removeSecondary, 0); |
|
|
|
|
|
|
|
|
|
this.postMerge(); |
|
|
|
|
return result; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
@ -78,53 +120,32 @@ MergeSort.prototype.sort = function(arr, start, end) { |
|
|
|
|
*/ |
|
|
|
|
MergeSort.prototype.merge = function(arr1, arr2) { |
|
|
|
|
var result = []; |
|
|
|
|
var e, x, y, v; |
|
|
|
|
|
|
|
|
|
this.V.instruct(this.V.removeTertiary, 100); |
|
|
|
|
var e; |
|
|
|
|
|
|
|
|
|
while (arr1.length > 0 || arr2.length > 0) { |
|
|
|
|
x = Visualizer.padding + result.length * (Visualizer.itemW + Visualizer.spacerW); |
|
|
|
|
y = Visualizer.padding * 3 + Visualizer.itemH * 2 |
|
|
|
|
|
|
|
|
|
if (arr1.length === 0) { |
|
|
|
|
e = arr2.shift(); |
|
|
|
|
result.push(e); |
|
|
|
|
|
|
|
|
|
this.V |
|
|
|
|
.instruct(this.V.item, 0, 'tertiary', x, y, e.value, '#8E5500') |
|
|
|
|
.instruct(this.V.message, 0, 4, 'One element left to merge.') |
|
|
|
|
.instruct(this.V.message, 100, 5, `Pushing ${e.value} to sub-result.`); |
|
|
|
|
this.midMerge(result.length, e.value, 'One element left to merge.'); |
|
|
|
|
} |
|
|
|
|
else if (arr2.length === 0) { |
|
|
|
|
e = arr1.shift(); |
|
|
|
|
result.push(e); |
|
|
|
|
|
|
|
|
|
this.V |
|
|
|
|
.instruct(this.V.item, 0, 'tertiary', x, y, e.value, '#8E5500') |
|
|
|
|
.instruct(this.V.message, 0, 4, 'One element left to merge.') |
|
|
|
|
.instruct(this.V.message, 100, 5, `Pushing ${e.value} to sub-result.`); |
|
|
|
|
this.midMerge(result.length, e.value, 'One element left to merge.'); |
|
|
|
|
} |
|
|
|
|
else if (arr1[0].value <= arr2[0].value) { |
|
|
|
|
e = arr1.shift() |
|
|
|
|
result.push(e); |
|
|
|
|
|
|
|
|
|
this.V |
|
|
|
|
.instruct(this.V.item, 0, 'tertiary', x, y, e.value, '#8E5500') |
|
|
|
|
.instruct(this.V.message, 0, 4, `${e.value} <= ${arr2[0].value}`) |
|
|
|
|
.instruct(this.V.message, 100, 5, `Pushing ${e.value} to sub-result.`); |
|
|
|
|
this.midMerge(result.length, e.value, `${e.value} <= ${arr2[0].value}`); |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
e = arr2.shift(); |
|
|
|
|
result.push(e); |
|
|
|
|
|
|
|
|
|
this.V |
|
|
|
|
.instruct(this.V.item, 0, 'tertiary', x, y, e.value, '#8E5500') |
|
|
|
|
.instruct(this.V.message, 0, 4, `${arr1[0].value} > ${e.value}`) |
|
|
|
|
.instruct(this.V.message, 100, 5, `Pushing ${e.value} to sub-result.`); |
|
|
|
|
this.midMerge(result.length, e.value, `${arr1[0].value} > ${e.value}`); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
this.comparisons++; |
|
|
|
|
this.V.instruct(this.V.message, 0, 1, `Comparisons: ${this.comparisons}`); |
|
|
|
|
this.updateComparisons(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
|