/** * */ var MergeSort = function() { //===== Inits. this.actions = []; this.comparisons = 0; //===== Action management. // this.reset = function(arr, start, end) { var len = arr.length; 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, '') .instruct(Itemgroup.message, 0, 0, 3, '') .instruct(Itemgroup.message, 0, 0, 4, '') .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 .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}]`); }; // this.preMerge = function(start, mid, end, len) { 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.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) }; // this.midMerge = function(index, 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.`); }; // 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 .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, 0, len) .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.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) }; /** * */ MergeSort.prototype.sort = function(arr, start, end) { this.reset(arr, start, end); 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); var arr1 = this.sort(arr, start, mid); var arr2 = this.sort(arr, mid + 1, end); this.preMerge(start, mid, end, arr.length); var result = this.merge(arr1, arr2); this.postMerge(arr.length); return result; }; /** * */ MergeSort.prototype.merge = function(arr1, arr2) { var result = []; var n; 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.'); } else if (arr2.length === 0) { n = arr1.shift(); result.push(n); this.midMerge(result.length, n, 'One element left to merge.'); } else if (arr1[0] <= arr2[0]) { n = arr1.shift() result.push(n); this.midMerge(result.length, n, `${n} <= ${arr2[0]}`); } else { n = arr2.shift(); result.push(n); this.midMerge(result.length, n, `${arr1[0]} > ${n}`); } this.comparisons++; this.updateComparisons(); } return result; };