/** * */ 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); /** * */ MergeSort.prototype.sort = function(arr, start, end) { this.initSort(arr, start, end); if (arr.length === 0) { return arr; } if (start === end) { this.splitSingle(start); return new Array(arr[start]); } var mid = start + Math.floor((end - start) / 2); this.preSort(start, mid, end); var arr1 = this.sort(arr, start, mid); var arr2 = this.sort(arr, mid + 1, end); this.preMerge(arr1, arr2, start, mid, end); var result = this.merge(arr1, arr2); this.postMerge(); return result; }; /** * */ MergeSort.prototype.merge = function(arr1, arr2) { var result = []; var e; while (arr1.length > 0 || arr2.length > 0) { if (arr1.length === 0) { e = arr2.shift(); result.push(e); this.midMerge(result.length, e.value, 'One element left to merge.'); } else if (arr2.length === 0) { e = arr1.shift(); result.push(e); 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.midMerge(result.length, e.value, `${e.value} <= ${arr2[0].value}`); } else { e = arr2.shift(); result.push(e); this.midMerge(result.length, e.value, `${arr1[0].value} > ${e.value}`); } this.comparisons++; this.updateComparisons(); } return result; };