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.
 
 
 

189 lines
5.5 KiB

/**
*
*/
var MergeSort = function() {
//===== Action management.
//
this.reset = function(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.');
};
//
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, 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(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)
};
//
this.midMerge = function(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.`);
};
//
this.updateComparisons = function() {
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.reset(arr.length);
if (arr.length === 0) {
return arr;
}
if (start === end) {
return [arr[start]];
}
var mid = start + Math.floor((end - start) / 2);
this.preSort(start, mid, end, arr.length);
var arr1 = this.sort(arr, start, mid);
var arr2 = this.sort(arr, mid + 1, end);
this.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.midMerge(arr2index, result.length - 1, n, '(last element)');
arr2index++;
}
else if (arr2.length === 0) {
n = arr1.shift();
result.push(n);
this.midMerge(arr1index, result.length - 1, n, '(last element)');
arr1index++;
}
else if (arr1[0] <= arr2[0]) {
n = arr1.shift()
result.push(n);
this.midMerge(arr1index, result.length - 1, n, `Compare heads: ${n} <= ${arr2[0]}`);
arr1index++;
}
else {
n = arr2.shift();
result.push(n);
this.midMerge(arr2index, result.length - 1, n, `Compare heads: ${arr1[0]} > ${n}`);
arr2index++;
}
this.comparisons++;
this.updateComparisons();
}
return result;
};