Quicksort visualization finished.

master
ben-burlingham 10 years ago
parent 4c28ba0029
commit 781d61628d
  1. 6
      index.html
  2. 9
      js/itemgroup.js
  3. 183
      js/quicksort.js
  4. 4
      js/visualizer.js

@ -10,9 +10,8 @@
<body>
for each one: in place? adaptive? stable? swaps. comparisons. random example. best case example. worst case example.
<!-- <h1>Quicksort discussion</h1>
<h1>Quicksort discussion</h1>
used by chrome. <br>
swap. highlight. (un)fade.
<div class="sorter"
data-algorithm='quick'
data-stable='Maybe'
@ -22,12 +21,11 @@
data-best-perf='O(n + m + 3k)'
data-worst-memory='0 (in place)'
></div>
-->
<h1>Mergesort discussion</h1>
used by firefox and safari. <br>
helpful: http://stackoverflow.com/questions/2967153/space-requirements-of-a-merge-sort<br>
<div class="sorter"
data-algorithm='merge'
data-stable='Maybe'

@ -58,11 +58,14 @@ var Itemgroup = {
if (i === indexA) {
x = indexB * (Visualizer.itemW + Visualizer.spacerW) + Visualizer.padding;
a = d3.select(this).select('text').text();
if (indexA === indexB) {
b = a;
}
}
else if (i === indexB) {
x = indexA * (Visualizer.itemW + Visualizer.spacerW) + Visualizer.padding;
b = d3.select(this).select('text').text();
}
return `translate(${x}, ${Visualizer.padding})`;
@ -72,8 +75,6 @@ var Itemgroup = {
return;
}
console.log(`indexA: ${indexA}, ${a}, indexB: ${indexB}, ${b}`);
// Undo the animation by restoring the original positions and swapping the values.
group.selectAll('g')
.attr('transform', function transform(d, i) {
@ -88,8 +89,6 @@ var Itemgroup = {
d3.select(this).select('text').text(a);
}
});
console.warn(`indexA: ${indexA}, ${a}, indexB: ${indexB}, ${b}`);
});
},

@ -1,27 +1,123 @@
/**
*
*/
var QuickSort = function(VisualizerInstance) {
var QuickSort = function() {
//===== Inits.
this.actions = [];
this.swaps = 0;
this.comparisons = 0;
this.V = VisualizerInstance;
this.V
.instruct(this.V.hideMarker, 0, 1)
.instruct(this.V.hideMarker, 0, 2)
.instruct(this.V.message, 0, 2, 'Swaps: ' + this.swaps)
.instruct(this.V.message, 0, 1, 'Comparisons: ' + this.comparisons);
//===== Action management.
//
this.preSort = function(left, right, pivot, len) {
this
.instruct(Itemgroup.message, 0, 0, 1, 'Comparisons: ' + this.comparisons)
.instruct(Itemgroup.message, 0, 0, 2, 'Swaps: ' + this.swaps)
.instruct(Itemgroup.opacity, 1, 0, 0, len, 1)
.instruct(Itemgroup.opacity, 1, 0, -1, left - 1, 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.message, 0, 0, 3, 'Sorting from [' + left + '] to [' + right + ']')
.instruct(Itemgroup.message, 0, 0, 4, '')
.instruct(Itemgroup.message, 0, 100, 5, '');
};
//
this.highlight = function(arr, left, right, pivot, msg) {
if (left >= right) {
return;
}
this
.instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0)
.instruct(Itemgroup.background, 1, 0, pivot, pivot, '#435C11')
.instruct(Itemgroup.background, 1, 0, left, left, '#0C1E42')
.instruct(Itemgroup.background, 1, 0, right, right, '#7F9EDB')
.instruct(Itemgroup.message, 0, 0, 1, `Comparisons: ${this.comparisons}`)
.instruct(Itemgroup.message, 0, 0, 4, `Pivot at [${pivot}] = ${arr[pivot]}`)
.instruct(Itemgroup.message, 0, 100, 5, msg)
// .instruct(Itemgroup.message, 0, 0, 5, msg)
// .instruct(Itemgroup.message, 0, 100, 1, `Comparisons: ${this.comparisons}`)
};
//
this.stop = function(arr, left, right, pivot, msg) {
this
.instruct(Itemgroup.background, 1, 0, 0, arr.length, Visualizer.bg0)
.instruct(Itemgroup.background, 1, 0, pivot, pivot, '#435C11')
.instruct(Itemgroup.background, 1, 0, left, left, '#0C1E42')
.instruct(Itemgroup.background, 1, 0, right, right, '#7F9EDB')
.instruct(Itemgroup.message, 0, 0, 4, `Pivot at [${pivot}] = ${arr[pivot]}`)
.instruct(Itemgroup.message, 0, 100, 5, msg)
};
//
this.swap = function(left, right) {
this
.instruct(Itemgroup.message, 0, 0, 2, 'Swaps: ' + this.swaps)
.instruct(Itemgroup.message, 0, 0, 4, 'Incremement left...')
.instruct(Itemgroup.message, 0, 0, 5, 'Decrement right...')
.instruct(Itemgroup.swap, 1, 300, left, right)
};
//
this.midSort = function(start, end, left, right) {
this
.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, 100, 5, `Recurse, sort from [${left}]-[${end}]`);
};
//
this.postSort = function() {
this
.instruct(Itemgroup.opacity, 1, 0, 0, this.ordered.length, 1)
.instruct(Itemgroup.background, 1, 0, 0, this.ordered.length, Visualizer.bg0)
.instruct(Itemgroup.message, 0, 0, 3, 'Sorting complete.')
.instruct(Itemgroup.message, 0, 0, 4, '')
.instruct(Itemgroup.message, 0, 0, 5, '');
};
};
QuickSort.prototype = Object.create(Sorter.prototype);
// NOTE adds to an instruction set
/**
*
*/
QuickSort.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, 1, 0, i, this.shuffled[i]);
}
this
.instruct(Itemgroup.foreground, 1, 0, 0, len, Visualizer.fg0)
.instruct(Itemgroup.background, 1, 0, 0, len, Visualizer.bg0)
.instruct(Itemgroup.opacity, 0, 0, 0, len, 0)
.instruct(Itemgroup.opacity, 2, 0, 0, len, 0)
};
/**
*
*/
QuickSort.prototype.sort = function(arr, start, end) {
if (end <= start) {
// message: Left and Right have crossed, start sorting sublists.
this.postSort();
return arr;
}
@ -29,94 +125,49 @@ QuickSort.prototype.sort = function(arr, start, end) {
var right = end;
var pivot = Math.floor((right + left) / 2);
var pivotval = arr[pivot].value;
var pivotval = arr[pivot];
var tmp;
var rval;
this.V
.instruct(this.V.marker, 0, 1, left, 'L')
.instruct(this.V.marker, 0, 2, right, 'R')
.instruct(this.V.showMarker, 0, 1)
.instruct(this.V.showMarker, 0, 2)
.instruct(this.V.unhighlight, 0)
.instruct(this.V.highlight, 0, pivot)
.instruct(this.V.fade, 0, -1, start - 1)
.instruct(this.V.fade, 0, end + 1, arr.length)
// Message: pivot chosen
.instruct(this.V.message, 0, 3, 'Sorting from [' + start + '] to [' + end + ']')
.instruct(this.V.message, 0, 4, '')
.instruct(this.V.message, 100, 5, '');
// Message: pivot chosen
this.preSort(left, right, pivot, arr.length);
while (left <= right) {
this.V.instruct(this.V.message, 0, 4, '');
this.V.instruct(this.V.message, 0, 5, '');
while (arr[left].value < pivotval) {
while (arr[left] < pivotval) {
this.comparisons++;
this.V
.instruct(this.V.message, 0, 4, `${arr[left].value} < ${pivotval}, increment left` )
.instruct(this.V.message, 0, 1, `Comparisons: ${this.comparisons}`)
.instruct(this.V.marker, 500, 1, left);
this.highlight(arr, left, right, pivot, `${arr[left]} < ${arr[pivot]}, increment left`);
left++;
}
this.V
.instruct(this.V.message, 0, 4, `Left stop: ${arr[left].value} >= ${pivotval}`)
.instruct(this.V.marker, 500, 1, left);
this.stop(arr, left, right, pivot, `Left stop: ${arr[left]} >= ${arr[pivot]}`);
while (arr[right].value > pivotval) {
while (arr[right] > pivotval) {
this.comparisons++;
this.V
.instruct(this.V.message, 0, 5, `${arr[right].value} > ${pivotval}, decrement right`)
.instruct(this.V.message, 0, 1, 'Comparisons: ' + this.comparisons)
.instruct(this.V.marker, 100, 2, right);
this.highlight(arr, left, right, pivot, `${arr[right]} > ${arr[pivot]}, decrement right`);
right--;
}
this.V
.instruct(this.V.message, 0, 5, `Right stop: ${arr[right].value} <= ${pivotval} `)
.instruct(this.V.marker, 100, 2, right);
this.stop(arr, left, right, pivot, `Right stop: ${arr[right]} <= ${arr[pivot]} `);
if (left <= right) {
tmp = arr[left];
arr[left] = arr[right];
arr[right] = tmp;
this.V.instruct(this.V.swap, 100, left, right);
left++;
right--;
this.swaps++;
this.V
.instruct(this.V.message, 0, 2, 'Swaps: ' + this.swaps)
.instruct(this.V.message, 0, 4, 'Incremement left...')
.instruct(this.V.message, 0, 5, 'Decrement right...')
.instruct(this.V.marker, 100, 1, left)
.instruct(this.V.marker, 100, 2, right)
this.swap(left - 1, right + 1);
}
}
this.V
.instruct(this.V.unfade, 0)
.instruct(this.V.unhighlight, 0)
.instruct(this.V.hideMarker, 0, 1)
.instruct(this.V.hideMarker, 0, 2)
.instruct(this.V.message, 0, 3, 'Sorting complete.')
.instruct(this.V.message, 0, 4, '')
.instruct(this.V.message, 0, 5, '');
this.midSort(start, end, left, right);
this.sort(arr, start, right);
this.sort(arr, left, end);
this.postSort();
return arr;
};

@ -98,11 +98,11 @@ Visualizer.prototype.go = function() {
// TODO add tabs for best/worst cases
// TODO add links to stats
// TODO fix init slider
// TODO fix init slider and match to width
// TODO heap sort
// TODO extra memory
// TODO width update
// TODO disable next button if no further actions and during action
// TODO source code tab
// NOTE functional programming discussion
// NOTE interesting (anti?)pattern here.

Loading…
Cancel
Save