/** * */ 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; };