Moved UI actions in UI object (rather than base level.

master
ben-burlingham 10 years ago
parent b61ea47464
commit 35303a9bc9
  1. 60
      index.html
  2. 56
      js/bubblesort.js
  3. 52
      js/insertionsort.js
  4. 56
      js/mergesort.js
  5. 75
      js/quicksort.js
  6. 55
      js/selectionsort.js
  7. 50
      js/shellsort.js
  8. 5
      js/visualizer.js

@ -18,8 +18,11 @@
<br> <br>
<h2>Quicksort discussion</h2> <h2>Quicksort discussion</h2>
<p>
used by chrome.<br>
source code link
</p>
<p>used by chrome.</p>
<div class="sorter" <div class="sorter"
data-algorithm='quick' data-algorithm='quick'
data-stable='Maybe' data-stable='Maybe'
@ -30,25 +33,15 @@
data-worst-memory='0 (in place)' data-worst-memory='0 (in place)'
></div> ></div>
<h2>Mergesort discussion</h2> <h2>Mergesort discussion</h2>
<p>used by firefox and safari. </p> <p>
used by firefox and safari.<br>
helpful: http://stackoverflow.com/questions/2967153/space-requirements-of-a-merge-sort<br> helpful: http://stackoverflow.com/questions/2967153/space-requirements-of-a-merge-sort<br>
<div class="sorter" source code link
data-algorithm='merge' </p>
data-stable='Maybe'
data-adaptive='Maybe'
data-worst-perf='O(n + m + 3k)'
data-avg-perf='O(n + m + 3k)'
data-best-perf='O(n + m + 3k)'
data-worst-memory='0 (in place)'
></div>
<h2>Shellsort discussion</h2>
several ways to pick gap width, but dependence on input data makes gap selection trivial. <br>
<div class="sorter" <div class="sorter"
data-algorithm='shell' data-algorithm='merge'
data-stable='Maybe' data-stable='Maybe'
data-adaptive='Maybe' data-adaptive='Maybe'
data-worst-perf='O(n + m + 3k)' data-worst-perf='O(n + m + 3k)'
@ -58,8 +51,12 @@
></div> ></div>
<h2>Selection sort discussion</h2> <h2>Selection sort discussion</h2>
<p>
http://stackoverflow.com/questions/15799034/insertion-sort-vs-selection-sort <br> http://stackoverflow.com/questions/15799034/insertion-sort-vs-selection-sort <br>
finds upstram minimum and swaps with current. finds upstram minimum and swaps with current.<br>
source code link
</p>
<div class="sorter" <div class="sorter"
data-algorithm='selection' data-algorithm='selection'
data-stable='Maybe' data-stable='Maybe'
@ -71,8 +68,12 @@
</div> </div>
<h2>Insertion sort discussion</h2> <h2>Insertion sort discussion</h2>
<p>
how is this different from bubble and selection. <br> how is this different from bubble and selection. <br>
swap. highlight. fade. swap. highlight. fade.<br>
source code link
</p>
<div class="sorter" <div class="sorter"
data-algorithm='insertion' data-algorithm='insertion'
data-stable='Maybe' data-stable='Maybe'
@ -83,10 +84,31 @@
data-worst-memory='0 (in place)' data-worst-memory='0 (in place)'
></div> ></div>
<h2>Shellsort discussion</h2>
<p>
several ways to pick gap width, but dependence on input data makes gap selection trivial.<br>
Insertion sort with gap of 1.<br>
source code link
</p>
<div class="sorter"
data-algorithm='shell'
data-stable='Maybe'
data-adaptive='Maybe'
data-worst-perf='O(n + m + 3k)'
data-avg-perf='O(n + m + 3k)'
data-best-perf='O(n + m + 3k)'
data-worst-memory='0 (in place)'
></div>
<h2>Bubble sort discussion</h2> <h2>Bubble sort discussion</h2>
<p>
how is this different from insertion and selection sorts. <br> how is this different from insertion and selection sorts. <br>
talk about turtles and rabbits, because search loops from beginning each time. Every number out of place means a new pass must be done. talk about turtles and rabbits, because search loops from beginning each time. Every number out of place means a new pass must be done.<br>
source code link
</p>
<div class="sorter" <div class="sorter"
data-algorithm='bubble' data-algorithm='bubble'
data-stable='Maybe' data-stable='Maybe'

@ -2,65 +2,67 @@
* *
*/ */
var BubbleSort = function() { var BubbleSort = function() {
//===== Action management. var _this = this;
//
this.preSort = function(arr) { this.ui = {
this presort: function presort(arr) {
_this
.instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0) .instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0)
.instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${this.comparisons}`) .instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${_this.comparisons}`)
.instruct(Itemgroup.message, 0, 0, 2, `Swaps: ${this.swaps}`) .instruct(Itemgroup.message, 0, 0, 2, `Swaps: ${_this.swaps}`)
.instruct(Itemgroup.message, 0, 0, 3, ``) .instruct(Itemgroup.message, 0, 0, 3, ``)
.instruct(Itemgroup.message, 0, 0, 4, ``) .instruct(Itemgroup.message, 0, 0, 4, ``)
.instruct(Itemgroup.message, 0, 100, 5, `Starting sort.`) .instruct(Itemgroup.message, 0, 100, 5, `Starting sort.`)
}; },
// //
this.midSort = function(arr, i) { midsort: function midsort(arr, i) {
this _this
.instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0) .instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0)
.instruct(Itemgroup.background, 1, 0, i, i, Visualizer.bg1) .instruct(Itemgroup.background, 1, 0, i, i, Visualizer.bg1)
.instruct(Itemgroup.background, 1, 0, (i - 1), (i - 1), Visualizer.bg1) .instruct(Itemgroup.background, 1, 0, (i - 1), (i - 1), Visualizer.bg1)
.instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${this.comparisons}`) .instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${_this.comparisons}`)
.instruct(Itemgroup.message, 0, 0, 3, `Comparing ${arr[i - 1]} and ${arr[i]}.`) .instruct(Itemgroup.message, 0, 0, 3, `Comparing ${arr[i - 1]} and ${arr[i]}.`)
.instruct(Itemgroup.message, 0, 0, 4, ``) .instruct(Itemgroup.message, 0, 0, 4, ``)
.instruct(Itemgroup.message, 0, 100, 5, ``) .instruct(Itemgroup.message, 0, 100, 5, ``)
}; },
// //
this.swap = function(arr, i) { swap: function swap(arr, i) {
this _this
.instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0) .instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0)
.instruct(Itemgroup.background, 1, 0, i, i, Visualizer.bg1) .instruct(Itemgroup.background, 1, 0, i, i, Visualizer.bg1)
.instruct(Itemgroup.background, 1, 0, (i - 1), (i - 1), Visualizer.bg1) .instruct(Itemgroup.background, 1, 0, (i - 1), (i - 1), Visualizer.bg1)
.instruct(Itemgroup.message, 0, 0, 2, `Swaps: ${this.swaps}`) .instruct(Itemgroup.message, 0, 0, 2, `Swaps: ${_this.swaps}`)
.instruct(Itemgroup.message, 0, 0, 4, `${arr[i]} > ${arr[i - 1]}`) .instruct(Itemgroup.message, 0, 0, 4, `${arr[i]} > ${arr[i - 1]}`)
.instruct(Itemgroup.message, 0, 0, 5, `Swap current and previous.`) .instruct(Itemgroup.message, 0, 0, 5, `Swap current and previous.`)
.instruct(Itemgroup.swap, 1, 300, i, i - 1) .instruct(Itemgroup.swap, 1, 300, i, i - 1)
}; },
// //
this.foundSwapped = function(arr) { foundSwapped: function foundSwapped(arr) {
this _this
.instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0) .instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0)
.instruct(Itemgroup.message, 0, 0, 3, ``) .instruct(Itemgroup.message, 0, 0, 3, ``)
.instruct(Itemgroup.message, 0, 0, 4, `Swapped elements found.`) .instruct(Itemgroup.message, 0, 0, 4, `Swapped elements found.`)
.instruct(Itemgroup.message, 0, 100, 5, `Recursing.`) .instruct(Itemgroup.message, 0, 100, 5, `Recursing.`)
}; },
// //
this.postSort = function(arr) { postsort: function postsort(arr) {
this _this
.instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0) .instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0)
.instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${this.comparisons}`) .instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${_this.comparisons}`)
.instruct(Itemgroup.message, 0, 0, 2, `Swaps: ${this.swaps}`) .instruct(Itemgroup.message, 0, 0, 2, `Swaps: ${_this.swaps}`)
.instruct(Itemgroup.message, 0, 0, 3, ``) .instruct(Itemgroup.message, 0, 0, 3, ``)
.instruct(Itemgroup.message, 0, 0, 4, ``) .instruct(Itemgroup.message, 0, 0, 4, ``)
.instruct(Itemgroup.message, 0, 100, 5, `Sorting complete.`) .instruct(Itemgroup.message, 0, 100, 5, `Sorting complete.`)
},
}; };
}; };
@ -101,11 +103,11 @@ BubbleSort.prototype.sort = function(arr) {
var swapped = false; var swapped = false;
var len = arr.length; var len = arr.length;
this.preSort(arr); this.ui.presort(arr);
for (i = 1; i < len; i++) { for (i = 1; i < len; i++) {
this.comparisons++; this.comparisons++;
this.midSort(arr, i); this.ui.midsort(arr, i);
if (arr[i - 1] > arr[i]) { if (arr[i - 1] > arr[i]) {
this.swaps++; this.swaps++;
@ -116,16 +118,16 @@ BubbleSort.prototype.sort = function(arr) {
swapped = true; swapped = true;
this.swap(arr, i, i - 1); this.ui.swap(arr, i, i - 1);
} }
} }
if (swapped === true) { if (swapped === true) {
this.foundSwapped(arr); this.ui.foundSwapped(arr);
this.sort(arr); this.sort(arr);
} }
this.postSort(arr); this.ui.postsort(arr);
return arr; return arr;
}; };

@ -2,56 +2,58 @@
* *
*/ */
var InsertionSort = function() { var InsertionSort = function() {
//===== Action management. var _this = this;
//
this.preSort = function(arr) { this.ui = {
this presort: function presort(arr) {
_this
.instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0) .instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0)
.instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${this.comparisons}`) .instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${_this.comparisons}`)
.instruct(Itemgroup.message, 0, 0, 2, `Swaps: ${this.swaps}`) .instruct(Itemgroup.message, 0, 0, 2, `Swaps: ${_this.swaps}`)
.instruct(Itemgroup.message, 0, 0, 3, ``) .instruct(Itemgroup.message, 0, 0, 3, ``)
.instruct(Itemgroup.message, 0, 0, 4, ``) .instruct(Itemgroup.message, 0, 0, 4, ``)
.instruct(Itemgroup.message, 0, 100, 5, `Starting sort.`) .instruct(Itemgroup.message, 0, 100, 5, `Starting sort.`)
}; },
// //
this.midSort = function(arr, i, j) { midsort: function midsort(arr, i, j) {
this _this
.instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0) .instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0)
.instruct(Itemgroup.background, 1, 0, j, j, Visualizer.bg1) .instruct(Itemgroup.background, 1, 0, j, j, Visualizer.bg1)
.instruct(Itemgroup.background, 1, 0, (j - 1), (j - 1), Visualizer.bg1) .instruct(Itemgroup.background, 1, 0, (j - 1), (j - 1), Visualizer.bg1)
.instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${this.comparisons}`) .instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${_this.comparisons}`)
.instruct(Itemgroup.message, 0, 0, 4, `Comparing [${j - 1}] and [${j}]`) .instruct(Itemgroup.message, 0, 0, 4, `Comparing [${j - 1}] and [${j}]`)
.instruct(Itemgroup.message, 0, 100, 5, ``) .instruct(Itemgroup.message, 0, 100, 5, ``)
}; },
// //
this.swap = function(arr, j) { swap: function swap(arr, j) {
this _this
.instruct(Itemgroup.message, 0, 0, 2, `Swaps: ${this.swaps}`) .instruct(Itemgroup.message, 0, 0, 2, `Swaps: ${_this.swaps}`)
.instruct(Itemgroup.message, 0, 0, 5, `${arr[j]} < ${arr[j - 1]}, swapped.`) .instruct(Itemgroup.message, 0, 0, 5, `${arr[j]} < ${arr[j - 1]}, swapped.`)
.instruct(Itemgroup.swap, 1, 300, j - 1, j) .instruct(Itemgroup.swap, 1, 300, j - 1, j)
if (j - 1 > 0) { if (j - 1 > 0) {
this.instruct(Itemgroup.message, 0, 0, 3, `Continuing downstream...`) _this.instruct(Itemgroup.message, 0, 0, 3, `Continuing downstream...`)
} }
else { else {
this.instruct(Itemgroup.message, 0, 0, 3, ``) _this.instruct(Itemgroup.message, 0, 0, 3, ``)
} }
}; },
// //
this.postSort = function(arr) { postsort: function postsort(arr) {
this _this
.instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0) .instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0)
.instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${this.comparisons}`) .instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${_this.comparisons}`)
.instruct(Itemgroup.message, 0, 0, 2, `Swaps: ${this.swaps}`) .instruct(Itemgroup.message, 0, 0, 2, `Swaps: ${_this.swaps}`)
.instruct(Itemgroup.message, 0, 0, 3, ``) .instruct(Itemgroup.message, 0, 0, 3, ``)
.instruct(Itemgroup.message, 0, 0, 4, ``) .instruct(Itemgroup.message, 0, 0, 4, ``)
.instruct(Itemgroup.message, 0, 100, 5, `Sorting complete.`) .instruct(Itemgroup.message, 0, 100, 5, `Sorting complete.`)
},
}; };
}; };
@ -93,12 +95,12 @@ InsertionSort.prototype.sort = function(arr) {
var j; var j;
var tmp; var tmp;
this.preSort(arr); this.ui.presort(arr);
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
for (j = i; j > 0; j--) { for (j = i; j > 0; j--) {
this.comparisons++; this.comparisons++;
this.midSort(arr, i, j); this.ui.midsort(arr, i, j);
if (arr[j - 1] > arr[j]) { if (arr[j - 1] > arr[j]) {
this.swaps++; this.swaps++;
@ -106,7 +108,7 @@ InsertionSort.prototype.sort = function(arr) {
arr[j - 1] = arr[j]; arr[j - 1] = arr[j];
arr[j] = tmp; arr[j] = tmp;
this.swap(arr, j); this.ui.swap(arr, j);
} }
else { else {
break; break;
@ -114,6 +116,6 @@ InsertionSort.prototype.sort = function(arr) {
} }
} }
this.postSort(arr); this.ui.postsort(arr);
return arr; return arr;
}; };

@ -2,25 +2,26 @@
* *
*/ */
var MergeSort = function() { var MergeSort = function() {
//===== Action management. var _this = this;
this.ui = {
// //
this.reset = function(len) { reset: function reset(len) {
this _this
.instruct(Itemgroup.background, 0, 0, '#f00', 0, len) .instruct(Itemgroup.background, 0, 0, '#f00', 0, len)
.instruct(Itemgroup.opacity, 0, 0, 0, len, 1) .instruct(Itemgroup.opacity, 0, 0, 0, len, 1)
.instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${this.comparisons}`) .instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${_this.comparisons}`)
.instruct(Itemgroup.message, 0, 0, 2, '') .instruct(Itemgroup.message, 0, 0, 2, '')
.instruct(Itemgroup.message, 0, 0, 3, '') .instruct(Itemgroup.message, 0, 0, 3, '')
.instruct(Itemgroup.message, 0, 0, 4, '') .instruct(Itemgroup.message, 0, 0, 4, '')
.instruct(Itemgroup.message, 0, 0, 5, 'Starting sort.'); .instruct(Itemgroup.message, 0, 0, 5, 'Starting sort.');
}; },
// //
this.preSort = function(start, mid, end, len) { presort: function presort(start, mid, end, len) {
this _this
.instruct(Itemgroup.message, 0, 0, 2, `Sorting [${start}] - [${end}]`) .instruct(Itemgroup.message, 0, 0, 2, `Sorting [${start}] - [${end}]`)
.instruct(Itemgroup.message, 0, 0, 3, 'Slicing and recursing...') .instruct(Itemgroup.message, 0, 0, 3, 'Slicing and recursing...')
// .instruct(Itemgroup.message, 0, 0, 4, `[${start}]-[${mid}] and [${mid + 1}]-[${end}]`) // .instruct(Itemgroup.message, 0, 0, 4, `[${start}]-[${mid}] and [${mid + 1}]-[${end}]`)
@ -30,24 +31,24 @@ var MergeSort = function() {
.instruct(Itemgroup.opacity, 1, 0, 0, len, 0) .instruct(Itemgroup.opacity, 1, 0, 0, len, 0)
.instruct(Itemgroup.opacity, 2, 100, 0, len, 0) .instruct(Itemgroup.opacity, 2, 100, 0, len, 0)
}; },
// //
this.preMerge = function(arr1, arr2, start, mid, end, len) { premerge: function premerge(arr1, arr2, start, mid, end, len) {
var len1 = arr1.length; var len1 = arr1.length;
var len2 = arr2.length; var len2 = arr2.length;
for (var i = 0; i < len1; i++) { for (var i = 0; i < len1; i++) {
this _this
.instruct(Itemgroup.text, 1, 0, i, arr1[i]); .instruct(Itemgroup.text, 1, 0, i, arr1[i]);
} }
for (var j = 0; j < len2; j++) { for (var j = 0; j < len2; j++) {
this _this
.instruct(Itemgroup.text, 1, 0, len1 + j, arr2[j]); .instruct(Itemgroup.text, 1, 0, len1 + j, arr2[j]);
} }
this _this
.instruct(Itemgroup.message, 0, 0, 2, ``) .instruct(Itemgroup.message, 0, 0, 2, ``)
.instruct(Itemgroup.message, 0, 0, 3, 'Merging slices:') .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, 4, `[${start}]-[${mid}] and [${mid + 1}]-[${end}]`)
@ -61,11 +62,11 @@ var MergeSort = function() {
.instruct(Itemgroup.opacity, 2, 0, 0, len, 0) .instruct(Itemgroup.opacity, 2, 0, 0, len, 0)
.instruct(Itemgroup.opacity, 1, 100, 0, len1 + len2 - 1, 1) .instruct(Itemgroup.opacity, 1, 100, 0, len1 + len2 - 1, 1)
}; },
// //
this.midMerge = function(indexG1, indexG2, value, message) { midmerge: function midmerge(indexG1, indexG2, value, message) {
this _this
.instruct(Itemgroup.opacity, 1, 0, indexG1, indexG1, 0) .instruct(Itemgroup.opacity, 1, 0, indexG1, indexG1, 0)
.instruct(Itemgroup.opacity, 2, 0, indexG2, indexG2, 1) .instruct(Itemgroup.opacity, 2, 0, indexG2, indexG2, 1)
@ -73,11 +74,12 @@ var MergeSort = function() {
.instruct(Itemgroup.message, 0, 0, 4, message) .instruct(Itemgroup.message, 0, 0, 4, message)
.instruct(Itemgroup.message, 0, 100, 5, `${value} pushed onto sub-result.`); .instruct(Itemgroup.message, 0, 100, 5, `${value} pushed onto sub-result.`);
}; },
// //
this.updateComparisons = function() { updateComparisons: function updateComparisons() {
this.instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${this.comparisons}`); _this.instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${_this.comparisons}`);
},
}; };
}; };
@ -118,7 +120,7 @@ MergeSort.prototype.init = function() {
* *
*/ */
MergeSort.prototype.sort = function(arr, start, end) { MergeSort.prototype.sort = function(arr, start, end) {
this.reset(arr.length); this.ui.reset(arr.length);
if (arr.length === 0) { if (arr.length === 0) {
return arr; return arr;
@ -130,11 +132,11 @@ MergeSort.prototype.sort = function(arr, start, end) {
var mid = start + Math.floor((end - start) / 2); var mid = start + Math.floor((end - start) / 2);
this.preSort(start, mid, end, arr.length); this.ui.presort(start, mid, end, arr.length);
var arr1 = this.sort(arr, start, mid); var arr1 = this.sort(arr, start, mid);
var arr2 = this.sort(arr, mid + 1, end); var arr2 = this.sort(arr, mid + 1, end);
this.preMerge(arr1, arr2, start, mid, end, arr.length); this.ui.premerge(arr1, arr2, start, mid, end, arr.length);
var result = this.merge(arr1, arr2); var result = this.merge(arr1, arr2);
return result; return result;
@ -156,33 +158,33 @@ MergeSort.prototype.merge = function(arr1, arr2) {
n = arr2.shift(); n = arr2.shift();
result.push(n); result.push(n);
this.midMerge(arr2index, result.length - 1, n, '(last element)'); this.ui.midmerge(arr2index, result.length - 1, n, '(last element)');
arr2index++; arr2index++;
} }
else if (arr2.length === 0) { else if (arr2.length === 0) {
n = arr1.shift(); n = arr1.shift();
result.push(n); result.push(n);
this.midMerge(arr1index, result.length - 1, n, '(last element)'); this.ui.midmerge(arr1index, result.length - 1, n, '(last element)');
arr1index++; arr1index++;
} }
else if (arr1[0] <= arr2[0]) { else if (arr1[0] <= arr2[0]) {
n = arr1.shift() n = arr1.shift()
result.push(n); result.push(n);
this.midMerge(arr1index, result.length - 1, n, `Compare heads: ${n} <= ${arr2[0]}`); this.ui.midmerge(arr1index, result.length - 1, n, `Compare heads: ${n} <= ${arr2[0]}`);
arr1index++; arr1index++;
} }
else { else {
n = arr2.shift(); n = arr2.shift();
result.push(n); result.push(n);
this.midMerge(arr2index, result.length - 1, n, `Compare heads: ${arr1[0]} > ${n}`); this.ui.midmerge(arr2index, result.length - 1, n, `Compare heads: ${arr1[0]} > ${n}`);
arr2index++; arr2index++;
} }
this.comparisons++; this.comparisons++;
this.updateComparisons(); this.ui.updateComparisons();
} }
return result; return result;

@ -2,46 +2,48 @@
* *
*/ */
var QuickSort = function() { var QuickSort = function() {
//===== Action management. var _this = this;
this.ui = {
// //
this.preSort = function(left, right, pivot, len) { presort: function presort(left, right, pivot, len) {
this _this
.instruct(Itemgroup.message, 0, 0, 1, 'Comparisons: ' + this.comparisons) .instruct(Itemgroup.message, 0, 0, 1, 'Comparisons: ' + _this.comparisons)
.instruct(Itemgroup.message, 0, 0, 2, 'Swaps: ' + this.swaps) .instruct(Itemgroup.message, 0, 0, 2, 'Swaps: ' + _this.swaps)
.instruct(Itemgroup.opacity, 1, 0, 0, len, 1) .instruct(Itemgroup.opacity, 1, 0, 0, len, 1)
.instruct(Itemgroup.opacity, 1, 0, -1, left - 1, 0.2) .instruct(Itemgroup.opacity, 1, 0, -1, left - 1, 0.2)
.instruct(Itemgroup.opacity, 1, 0, right + 1, len, 0.2) .instruct(Itemgroup.opacity, 1, 0, right + 1, len, 0.2)
.instruct(Itemgroup.background, 1, 0, 0, this.ordered.length, Visualizer.bg0) .instruct(Itemgroup.background, 1, 0, 0, _this.ordered.length, Visualizer.bg0)
.instruct(Itemgroup.message, 0, 0, 3, 'Sorting from [' + left + '] to [' + right + ']') .instruct(Itemgroup.message, 0, 0, 3, 'Sorting from [' + left + '] to [' + right + ']')
.instruct(Itemgroup.message, 0, 0, 4, '') .instruct(Itemgroup.message, 0, 0, 4, '')
.instruct(Itemgroup.message, 0, 100, 5, 'Starting sort.'); .instruct(Itemgroup.message, 0, 100, 5, 'Starting sort.');
}; },
// //
this.highlight = function(arr, left, right, pivot, msg) { highlight: function highlight(arr, left, right, pivot, msg) {
if (left >= right) { if (left >= right) {
return; return;
} }
this _this
.instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0) .instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0)
.instruct(Itemgroup.background, 1, 0, pivot, pivot, '#435C11') .instruct(Itemgroup.background, 1, 0, pivot, pivot, '#435C11')
.instruct(Itemgroup.background, 1, 0, left, left, '#0C1E42') .instruct(Itemgroup.background, 1, 0, left, left, '#0C1E42')
.instruct(Itemgroup.background, 1, 0, right, right, '#7F9EDB') .instruct(Itemgroup.background, 1, 0, right, right, '#7F9EDB')
.instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${this.comparisons}`) .instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${_this.comparisons}`)
.instruct(Itemgroup.message, 0, 0, 4, `Pivot at [${pivot}] = ${arr[pivot]}`) .instruct(Itemgroup.message, 0, 0, 4, `Pivot at [${pivot}] = ${arr[pivot]}`)
.instruct(Itemgroup.message, 0, 100, 5, msg) .instruct(Itemgroup.message, 0, 100, 5, msg)
// .instruct(Itemgroup.message, 0, 0, 5, msg) // .instruct(Itemgroup.message, 0, 0, 5, msg)
// .instruct(Itemgroup.message, 0, 100, 1, `Comparisons: ${this.comparisons}`) // .instruct(Itemgroup.message, 0, 100, 1, `Comparisons: ${_this.comparisons}`)
}; },
// //
this.stop = function(arr, left, right, pivot, msg) { stop: function stop(arr, left, right, pivot, msg) {
this _this
.instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0) .instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0)
.instruct(Itemgroup.background, 1, 0, pivot, pivot, '#435C11') .instruct(Itemgroup.background, 1, 0, pivot, pivot, '#435C11')
.instruct(Itemgroup.background, 1, 0, left, left, '#0C1E42') .instruct(Itemgroup.background, 1, 0, left, left, '#0C1E42')
@ -49,35 +51,36 @@ var QuickSort = function() {
.instruct(Itemgroup.message, 0, 0, 4, `Pivot at [${pivot}] = ${arr[pivot]}`) .instruct(Itemgroup.message, 0, 0, 4, `Pivot at [${pivot}] = ${arr[pivot]}`)
.instruct(Itemgroup.message, 0, 100, 5, msg) .instruct(Itemgroup.message, 0, 100, 5, msg)
}; },
// //
this.swap = function(left, right) { swap: function swap(left, right) {
this _this
.instruct(Itemgroup.message, 0, 0, 2, 'Swaps: ' + this.swaps) .instruct(Itemgroup.message, 0, 0, 2, 'Swaps: ' + _this.swaps)
.instruct(Itemgroup.message, 0, 0, 4, 'Incremement left...') .instruct(Itemgroup.message, 0, 0, 4, 'Incremement left...')
.instruct(Itemgroup.message, 0, 0, 5, 'Decrement right...') .instruct(Itemgroup.message, 0, 0, 5, 'Decrement right...')
.instruct(Itemgroup.swap, 1, 300, left, right) .instruct(Itemgroup.swap, 1, 300, left, right)
}; },
// //
this.midSort = function(start, end, left, right) { midsort: function midsort(start, end, left, right) {
this _this
.instruct(Itemgroup.message, 0, 0, 3, 'Left has passed right.') .instruct(Itemgroup.message, 0, 0, 3, 'Left has passed right.')
.instruct(Itemgroup.message, 0, 0, 4, `Recurse, sort from [${start}]-[${right}]`) .instruct(Itemgroup.message, 0, 0, 4, `Recurse, sort from [${start}]-[${right}]`)
.instruct(Itemgroup.message, 0, 100, 5, `Recurse, sort from [${left}]-[${end}]`); .instruct(Itemgroup.message, 0, 100, 5, `Recurse, sort from [${left}]-[${end}]`);
}; },
// //
this.postSort = function() { postsort: function postsort() {
this _this
.instruct(Itemgroup.opacity, 1, 0, 0, this.ordered.length, 1) .instruct(Itemgroup.opacity, 1, 0, 0, _this.ordered.length, 1)
.instruct(Itemgroup.background, 1, 0, 0, this.ordered.length, Visualizer.bg0) .instruct(Itemgroup.background, 1, 0, 0, _this.ordered.length, Visualizer.bg0)
.instruct(Itemgroup.message, 0, 0, 3, 'Sorting complete.') .instruct(Itemgroup.message, 0, 0, 3, 'Sorting complete.')
.instruct(Itemgroup.message, 0, 0, 4, '') .instruct(Itemgroup.message, 0, 0, 4, '')
.instruct(Itemgroup.message, 0, 0, 5, ''); .instruct(Itemgroup.message, 0, 0, 5, '');
}; },
}
}; };
QuickSort.prototype = Object.create(Sorter.prototype); QuickSort.prototype = Object.create(Sorter.prototype);
@ -114,7 +117,7 @@ QuickSort.prototype.init = function() {
*/ */
QuickSort.prototype.sort = function(arr, start, end) { QuickSort.prototype.sort = function(arr, start, end) {
if (end <= start) { if (end <= start) {
this.postSort(); this.ui.postsort();
return arr; return arr;
} }
@ -126,24 +129,24 @@ QuickSort.prototype.sort = function(arr, start, end) {
var tmp; var tmp;
var rval; var rval;
this.preSort(left, right, pivot, arr.length); this.ui.presort(left, right, pivot, arr.length);
while (left <= right) { while (left <= right) {
while (arr[left] < pivotval) { while (arr[left] < pivotval) {
this.comparisons++; this.comparisons++;
this.highlight(arr, left, right, pivot, `${arr[left]} < ${arr[pivot]}, increment left`); this.ui.highlight(arr, left, right, pivot, `${arr[left]} < ${arr[pivot]}, increment left`);
left++; left++;
} }
this.stop(arr, left, right, pivot, `Left stop: ${arr[left]} >= ${arr[pivot]}`); this.ui.stop(arr, left, right, pivot, `Left stop: ${arr[left]} >= ${arr[pivot]}`);
while (arr[right] > pivotval) { while (arr[right] > pivotval) {
this.comparisons++; this.comparisons++;
this.highlight(arr, left, right, pivot, `${arr[right]} > ${arr[pivot]}, decrement right`); this.ui.highlight(arr, left, right, pivot, `${arr[right]} > ${arr[pivot]}, decrement right`);
right--; right--;
} }
this.stop(arr, left, right, pivot, `Right stop: ${arr[right]} <= ${arr[pivot]} `); this.ui.stop(arr, left, right, pivot, `Right stop: ${arr[right]} <= ${arr[pivot]} `);
if (left <= right) { if (left <= right) {
tmp = arr[left]; tmp = arr[left];
@ -154,16 +157,16 @@ QuickSort.prototype.sort = function(arr, start, end) {
right--; right--;
this.swaps++; this.swaps++;
this.swap(left - 1, right + 1); this.ui.swap(left - 1, right + 1);
} }
} }
this.midSort(start, end, left, right); this.ui.midsort(start, end, left, right);
this.sort(arr, start, right); this.sort(arr, start, right);
this.sort(arr, left, end); this.sort(arr, left, end);
this.postSort(); this.ui.postsort();
return arr; return arr;
}; };

@ -2,62 +2,65 @@
* *
*/ */
var SelectionSort = function() { var SelectionSort = function() {
//===== Action management. var _this = this;
this.ui = {
// //
this.preSort = function(arr) { presort: function presort(arr) {
this _this
.instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0) .instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0)
.instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${this.comparisons}`) .instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${_this.comparisons}`)
.instruct(Itemgroup.message, 0, 0, 2, `Swaps: ${this.swaps}`) .instruct(Itemgroup.message, 0, 0, 2, `Swaps: ${_this.swaps}`)
.instruct(Itemgroup.message, 0, 0, 3, ``) .instruct(Itemgroup.message, 0, 0, 3, ``)
.instruct(Itemgroup.message, 0, 0, 4, ``) .instruct(Itemgroup.message, 0, 0, 4, ``)
.instruct(Itemgroup.message, 0, 100, 5, `Starting sort.`) .instruct(Itemgroup.message, 0, 100, 5, `Starting sort.`)
}; },
// //
this.midSort = function(arr, i, j, min) { midsort: function midsort(arr, i, j, min) {
this _this
.instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0) .instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0)
.instruct(Itemgroup.background, 1, 0, j, j, Visualizer.bg1) .instruct(Itemgroup.background, 1, 0, j, j, Visualizer.bg1)
.instruct(Itemgroup.background, 1, 0, i, i, '#435C11') .instruct(Itemgroup.background, 1, 0, i, i, '#435C11')
.instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${this.comparisons}`) .instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${_this.comparisons}`)
.instruct(Itemgroup.message, 0, 0, 3, `Current value: ${arr[i]}`) .instruct(Itemgroup.message, 0, 0, 3, `Current value: ${arr[i]}`)
.instruct(Itemgroup.message, 0, 0, 4, `Current minimum: ${arr[min]}`) .instruct(Itemgroup.message, 0, 0, 4, `Current minimum: ${arr[min]}`)
.instruct(Itemgroup.message, 0, 100, 5, `Comparing: ${arr[min]} and ${arr[j]}`) .instruct(Itemgroup.message, 0, 100, 5, `Comparing: ${arr[min]} and ${arr[j]}`)
}; },
// //
this.newmin = function(arr, min) { newmin: function newmin(arr, min) {
this _this
.instruct(Itemgroup.message, 0, 0, 4, `New minimum: ${arr[min]}`) .instruct(Itemgroup.message, 0, 0, 4, `New minimum: ${arr[min]}`)
.instruct(Itemgroup.message, 0, 100, 5, ``) .instruct(Itemgroup.message, 0, 100, 5, ``)
}; },
// //
this.swap = function(arr, i, min) { swap: function swap(arr, i, min) {
this _this
.instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0) .instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0)
.instruct(Itemgroup.background, 1, 0, i, i, Visualizer.bg1) .instruct(Itemgroup.background, 1, 0, i, i, Visualizer.bg1)
.instruct(Itemgroup.background, 1, 0, min, min, Visualizer.bg1) .instruct(Itemgroup.background, 1, 0, min, min, Visualizer.bg1)
.instruct(Itemgroup.message, 0, 0, 2, `Swaps: ${this.swaps}`) .instruct(Itemgroup.message, 0, 0, 2, `Swaps: ${_this.swaps}`)
.instruct(Itemgroup.message, 0, 0, 4, ``) .instruct(Itemgroup.message, 0, 0, 4, ``)
.instruct(Itemgroup.message, 0, 0, 5, `Swap current and minimum.`) .instruct(Itemgroup.message, 0, 0, 5, `Swap current and minimum.`)
.instruct(Itemgroup.swap, 1, 300, i, min) .instruct(Itemgroup.swap, 1, 300, i, min)
}; },
// //
this.postSort = function(arr) { postsort: function postsort(arr) {
this _this
.instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0) .instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0)
.instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${this.comparisons}`) .instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${_this.comparisons}`)
.instruct(Itemgroup.message, 0, 0, 2, `Swaps: ${this.swaps}`) .instruct(Itemgroup.message, 0, 0, 2, `Swaps: ${_this.swaps}`)
.instruct(Itemgroup.message, 0, 0, 3, ``) .instruct(Itemgroup.message, 0, 0, 3, ``)
.instruct(Itemgroup.message, 0, 0, 4, ``) .instruct(Itemgroup.message, 0, 0, 4, ``)
.instruct(Itemgroup.message, 0, 100, 5, `Sorting complete.`) .instruct(Itemgroup.message, 0, 100, 5, `Sorting complete.`)
},
}; };
}; };
@ -100,17 +103,17 @@ SelectionSort.prototype.sort = function(arr) {
var tmp; var tmp;
var min; var min;
this.preSort(arr); this.ui.presort(arr);
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
min = i; min = i;
for (j = i + 1; j < len; j++) { for (j = i + 1; j < len; j++) {
this.comparisons++; this.comparisons++;
this.midSort(arr, i, j, min); this.ui.midsort(arr, i, j, min);
if (arr[j] < arr[min]) { if (arr[j] < arr[min]) {
min = j; min = j;
this.newmin(arr, min); this.ui.newmin(arr, min);
} }
} }
@ -120,11 +123,11 @@ SelectionSort.prototype.sort = function(arr) {
arr[i] = arr[min]; arr[i] = arr[min];
arr[min] = tmp; arr[min] = tmp;
this.swap(arr, i, min); this.ui.swap(arr, i, min);
} }
} }
this.postSort(arr); this.ui.postsort(arr);
return arr; return arr;
}; };

@ -2,56 +2,58 @@
* *
*/ */
var ShellSort = function() { var ShellSort = function() {
//===== Action management. var _this = this;
//
this.preSort = function(arr, i, gap) { this.ui = {
this presort: function presort(arr, i, gap) {
_this
.instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0) .instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0)
.instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${this.comparisons}`) .instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${_this.comparisons}`)
.instruct(Itemgroup.message, 0, 0, 2, `Swaps: ${this.swaps}`) .instruct(Itemgroup.message, 0, 0, 2, `Swaps: ${_this.swaps}`)
.instruct(Itemgroup.message, 0, 0, 3, `Gap: ${gap}`) .instruct(Itemgroup.message, 0, 0, 3, `Gap: ${gap}`)
.instruct(Itemgroup.message, 0, 0, 4, ``) .instruct(Itemgroup.message, 0, 0, 4, ``)
.instruct(Itemgroup.message, 0, 100, 5, `Starting sort at index ${i}.`) .instruct(Itemgroup.message, 0, 100, 5, `Starting sort at index ${i}.`)
}; },
// //
this.midSort = function(arr, i, j, gap) { midsort: function midsort(arr, i, j, gap) {
this _this
.instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0) .instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0)
.instruct(Itemgroup.background, 1, 0, j, j, Visualizer.bg1) .instruct(Itemgroup.background, 1, 0, j, j, Visualizer.bg1)
.instruct(Itemgroup.background, 1, 0, (j - gap), (j - gap), Visualizer.bg1) .instruct(Itemgroup.background, 1, 0, (j - gap), (j - gap), Visualizer.bg1)
.instruct(Itemgroup.message, 0, 0, 4, `Comparing [${j - gap}] and [${j}]`) .instruct(Itemgroup.message, 0, 0, 4, `Comparing [${j - gap}] and [${j}]`)
.instruct(Itemgroup.message, 0, 100, 5, ``) .instruct(Itemgroup.message, 0, 100, 5, ``)
}; },
// //
this.swap = function(arr, j, gap) { swap: function swap(arr, j, gap) {
this _this
.instruct(Itemgroup.message, 0, 100, 4, `${arr[j]} < ${arr[j - gap]}, swap required.`) .instruct(Itemgroup.message, 0, 100, 4, `${arr[j]} < ${arr[j - gap]}, swap required.`)
.instruct(Itemgroup.swap, 1, 300, j - gap, j) .instruct(Itemgroup.swap, 1, 300, j - gap, j)
if (j - gap > 0) { if (j - gap > 0) {
this _this
.instruct(Itemgroup.message, 0, 100, 5, `Continuing downstream...`) .instruct(Itemgroup.message, 0, 100, 5, `Continuing downstream...`)
} }
}; },
// //
this.noswap = function(arr, j, gap) { noswap: function noswap(arr, j, gap) {
this _this
.instruct(Itemgroup.message, 0, 0, 4, `${arr[j]} > ${arr[j - gap]}, no swap required.`) .instruct(Itemgroup.message, 0, 0, 4, `${arr[j]} > ${arr[j - gap]}, no swap required.`)
.instruct(Itemgroup.message, 0, 100, 5, ``) .instruct(Itemgroup.message, 0, 100, 5, ``)
}; },
// //
this.postSort = function(arr) { postsort: function postsort(arr) {
this _this
.instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0) .instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0)
.instruct(Itemgroup.message, 0, 0, 3, ``) .instruct(Itemgroup.message, 0, 0, 3, ``)
.instruct(Itemgroup.message, 0, 0, 4, ``) .instruct(Itemgroup.message, 0, 0, 4, ``)
.instruct(Itemgroup.message, 0, 100, 5, `Ready for insertion sort.`) .instruct(Itemgroup.message, 0, 100, 5, `Ready for insertion sort.`)
}
}; };
}; };
@ -94,11 +96,11 @@ ShellSort.prototype.sort = function(arr) {
var i, j; var i, j;
for (i = 0; i < gap; i++) { for (i = 0; i < gap; i++) {
this.preSort(arr, i, gap); this.ui.presort(arr, i, gap);
this.gapSort(arr, i, gap); this.gapSort(arr, i, gap);
} }
this.postSort(arr); this.ui.postsort(arr);
return arr; return arr;
}; };
@ -112,7 +114,7 @@ ShellSort.prototype.gapSort = function(arr, start, gap) {
for (i = start; i < len; i += gap) { for (i = start; i < len; i += gap) {
for (j = i; j > start; j -= gap) { for (j = i; j > start; j -= gap) {
this.midSort(arr, i, j, gap); this.ui.midsort(arr, i, j, gap);
this.comparisons++; this.comparisons++;
if (arr[j - gap] > arr[j]) { if (arr[j - gap] > arr[j]) {
@ -121,10 +123,10 @@ ShellSort.prototype.gapSort = function(arr, start, gap) {
arr[j - gap] = arr[j]; arr[j - gap] = arr[j];
arr[j] = tmp; arr[j] = tmp;
this.swap(arr, j, gap); this.ui.swap(arr, j, gap);
} }
else { else {
this.noswap(arr, j, gap); this.ui.noswap(arr, j, gap);
break; break;
} }
} }

@ -104,9 +104,8 @@ Visualizer.prototype.go = function() {
// TODO add links to stats // TODO add links to stats
// TODO heap sort // TODO heap sort
// TODO disable next button if no further actions and during action // TODO radix sort
// TODO source code link and add all action management to .foo object in class // TODO in quicksort, change color or element that is in final position
// TODO change pause/play state on slider change
// NOTE functional programming discussion // NOTE functional programming discussion
// NOTE interesting (anti?)pattern here. // NOTE interesting (anti?)pattern here.

Loading…
Cancel
Save