You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
191 lines
5.8 KiB
191 lines
5.8 KiB
/**
|
|
*
|
|
*/
|
|
var MergeSort = function() {
|
|
var _this = this;
|
|
|
|
this.ui = {
|
|
//
|
|
reset: function reset(len) {
|
|
_this
|
|
.instruct(Itemgroup.background, 0, 0, '#f00', 0, len)
|
|
|
|
.instruct(Itemgroup.opacity, 0, 0, 0, len, 1)
|
|
|
|
.instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${_this.comparisons}`)
|
|
.instruct(Itemgroup.message, 0, 0, 2, '')
|
|
.instruct(Itemgroup.message, 0, 0, 3, '')
|
|
.instruct(Itemgroup.message, 0, 0, 4, '')
|
|
.instruct(Itemgroup.message, 0, 0, 5, 'Starting sort.');
|
|
},
|
|
|
|
//
|
|
presort: function presort(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, 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)
|
|
},
|
|
|
|
//
|
|
premerge: function premerge(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, 2, 0, 0, len, 0)
|
|
|
|
.instruct(Itemgroup.opacity, 1, 100, 0, len1 + len2 - 1, 1)
|
|
},
|
|
|
|
//
|
|
midmerge: function midmerge(indexG1, indexG2, value, message) {
|
|
_this
|
|
.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.`);
|
|
},
|
|
|
|
//
|
|
updateComparisons: function updateComparisons() {
|
|
_this.instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${_this.comparisons}`);
|
|
},
|
|
};
|
|
};
|
|
|
|
MergeSort.prototype = Object.create(Sorter.prototype);
|
|
|
|
/**
|
|
*
|
|
*/
|
|
MergeSort.prototype.init = function() {
|
|
var len = this.shuffled.length;
|
|
|
|
this.actions = [];
|
|
this.comparisons = 0;
|
|
|
|
this
|
|
.instruct(Itemgroup.items, 0, 0, len)
|
|
.instruct(Itemgroup.items, 1, 0, len)
|
|
.instruct(Itemgroup.items, 2, 0, len)
|
|
|
|
for (var i = 0; i < len; i++) {
|
|
this.instruct(Itemgroup.text, 0, 0, i, this.shuffled[i]);
|
|
}
|
|
|
|
this
|
|
.instruct(Itemgroup.foreground, 0, 0, 0, len, Visualizer.fg0)
|
|
.instruct(Itemgroup.background, 0, 0, 0, len, Visualizer.bg0)
|
|
|
|
.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, len, 0)
|
|
.instruct(Itemgroup.foreground, 2, 0, 0, len, Visualizer.fg2)
|
|
.instruct(Itemgroup.background, 2, 100, 0, len, Visualizer.bg2);
|
|
};
|
|
|
|
/**
|
|
*
|
|
*/
|
|
MergeSort.prototype.sort = function(arr, start, end) {
|
|
this.ui.reset(arr.length);
|
|
|
|
if (arr.length === 0) {
|
|
return arr;
|
|
}
|
|
|
|
if (start === end) {
|
|
return [arr[start]];
|
|
}
|
|
|
|
var mid = start + Math.floor((end - start) / 2);
|
|
|
|
this.ui.presort(start, mid, end, arr.length);
|
|
var arr1 = this.sort(arr, start, mid);
|
|
var arr2 = this.sort(arr, mid + 1, end);
|
|
|
|
this.ui.premerge(arr1, arr2, start, mid, end, arr.length);
|
|
var result = this.merge(arr1, arr2);
|
|
|
|
return result;
|
|
};
|
|
|
|
/**
|
|
*
|
|
*/
|
|
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.ui.midmerge(arr2index, result.length - 1, n, '(last element)');
|
|
arr2index++;
|
|
}
|
|
else if (arr2.length === 0) {
|
|
n = arr1.shift();
|
|
result.push(n);
|
|
|
|
this.ui.midmerge(arr1index, result.length - 1, n, '(last element)');
|
|
arr1index++;
|
|
}
|
|
else if (arr1[0] <= arr2[0]) {
|
|
n = arr1.shift()
|
|
result.push(n);
|
|
|
|
this.ui.midmerge(arr1index, result.length - 1, n, `Compare heads: ${n} <= ${arr2[0]}`);
|
|
arr1index++;
|
|
}
|
|
else {
|
|
n = arr2.shift();
|
|
result.push(n);
|
|
|
|
this.ui.midmerge(arr2index, result.length - 1, n, `Compare heads: ${arr1[0]} > ${n}`);
|
|
arr2index++;
|
|
}
|
|
|
|
this.comparisons++;
|
|
this.ui.updateComparisons();
|
|
}
|
|
|
|
return result;
|
|
};
|
|
|