Built sorter property into visualizer.

master
ben-burlingham 10 years ago
parent d01bdb503d
commit 397691a463
  1. 74
      index.html
  2. 8
      js/bubblesort.js
  3. 6
      js/insertionsort.js
  4. 22
      js/mergesort.js
  5. 14
      js/quicksort.js
  6. 8
      js/selectionsort.js
  7. 24
      js/shellsort.js
  8. 2
      js/sorter.js
  9. 175
      js/visualizer.js

@ -61,25 +61,42 @@
<body> <body>
for each one: in place? adaptive? stable? swaps. comparisons. random example. best case example. worst case example. 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 used by chrome. <br>
<div class="sorter"></div> swap. highlight. (un)fade.
<div class="sorter" data-algorithm='quick'></div>
<h1>Mergesort discussion</h1> <h1>Mergesort discussion</h1>
used by firefox and safari used by firefox and safari. <br>
<div class="sorter"></div> <div class="sorter" data-algorithm='merge'></div>
<h1>Shellsort discussion</h1> <h1>Shellsort discussion</h1>
several ways to pick gap width, but dependence on input data makes gap selection trivial several ways to pick gap width, but dependence on input data makes gap selection trivial. <br>
swap. highlight. fade.
<div class="sorter"></div> <div class="sorter" data-algorithm='shell'></div>
<h1>Selection sort discussion</h1> <h1>Selection sort discussion</h1>
http://stackoverflow.com/questions/15799034/insertion-sort-vs-selection-sort http://stackoverflow.com/questions/15799034/insertion-sort-vs-selection-sort <br>
swap. highlight. fade.
<div class="sorter" data-algorithm='selection'></div>
<h1>insertion sort discussion</h1>
how is this different from bubble and selection. <br>
swap. highlight. fade.
<div class="sorter" data-algorithm='insertion'></div>
<h1>bubble sort discussion</h1>
how is this different from insertion and selection sorts. <br>
swap. highlight. fade.
<div class="sorter" data-algorithm='bubble'></div>
<h1>radix sort discussion</h1>
<div class="sorter" data-algorithm='radix'></div>
<!-- <!--
<h1>Heapsort discussion</h1> <h1>Heapsort discussion</h1>
@ -109,36 +126,39 @@
<script type='text/javascript'> <script type='text/javascript'>
var dump = function(arr) { var dump = function(arr) {
console.log(arr)
var d = []; var d = [];
arr.forEach(function(obj) { arr.forEach(function(obj) {
d.push(obj.value); d.push(obj.value);
}) })
return d.join(','); // return d.join(',');
} };
var SS = new RadixSort(); // var SS = new RadixSort();
var data = SS.generate(15); // var data = SS.generate(15);
console.log('DATA: ' + dump(data)); // console.log('DATA: ' + dump(data));
var shuffled = SS.shuffle(data); // var shuffled = SS.shuffle(data);
console.log('SHUFFLED: ' + dump(shuffled)); // console.log('SHUFFLED: ' + dump(shuffled));
var ordered = Object.create(shuffled); // var ordered = Object.create(shuffled);
ordered = SS.sort(ordered, 0, ordered.length - 1); // ordered = SS.sort(ordered, 0, ordered.length - 1);
console.log('ORDERED: ' + dump(ordered)); // console.log('ORDERED: ' + dump(ordered));
// Wrap anonymous function to avoid polluting global namespace. // Wrap anonymous function to avoid polluting global namespace.
// (function() { (function() {
// var elements = document.querySelectorAll('.sorter'); var elements = document.querySelectorAll('.sorter');
// for (key in elements) { var V;
// if (elements.hasOwnProperty(key)) { for (key in elements) {
// new Visualizer(elements[key]); if (elements.hasOwnProperty(key)) {
// } V = new Visualizer(elements[key]);
// } // V.init();
// })(); }
}
})();
</script> </script>
</body> </body>
</html> </html>

@ -1,16 +1,16 @@
/** /**
* *
*/ */
var Bubblesort = function() { var BubbleSort = function() {
this.instructions = []; this.instructions = [];
}; };
Bubblesort.prototype = Object.create(Sorter.prototype); BubbleSort.prototype = Object.create(Sorter.prototype);
/** /**
* *
*/ */
Bubblesort.prototype.sort = function(arr) { BubbleSort.prototype.sort = function(arr) {
var i; var i;
var swapped = false; var swapped = false;
var len = arr.length; var len = arr.length;
@ -20,7 +20,7 @@ Bubblesort.prototype.sort = function(arr) {
if (arr[i - 1].value > arr[i].value) { if (arr[i - 1].value > arr[i].value) {
this.swap(arr, i, i - 1); this.swap(arr, i, i - 1);
swapped = true; swapped = true;
console.log(dump(arr)); // console.log(dump(arr));
} }
} }

@ -1,16 +1,16 @@
/** /**
* *
*/ */
var Insertionsort = function() { var InsertionSort = function() {
this.instructions = []; this.instructions = [];
}; };
Insertionsort.prototype = Object.create(Sorter.prototype); InsertionSort.prototype = Object.create(Sorter.prototype);
/** /**
* *
*/ */
Insertionsort.prototype.sort = function(arr) { InsertionSort.prototype.sort = function(arr) {
var len = arr.length; var len = arr.length;
var i; var i;
var j; var j;

@ -1,22 +1,22 @@
/** /**
* *
*/ */
var Mergesort = function() { var MergeSort = function() {
this.instructions = []; this.instructions = [];
}; };
Mergesort.prototype = Object.create(Sorter.prototype); MergeSort.prototype = Object.create(Sorter.prototype);
/** /**
* *
*/ */
Mergesort.prototype.addInstruction = function(operation, left, right, mid) { MergeSort.prototype.addInstruction = function(operation, left, right, mid) {
console.log({ // console.log({
operation: operation, // operation: operation,
left: left, // left: left,
right: right, // right: right,
mid: mid // mid: mid
}); // });
this.instructions.push({ this.instructions.push({
operation: operation, operation: operation,
@ -28,7 +28,7 @@ Mergesort.prototype.addInstruction = function(operation, left, right, mid) {
/** /**
* *
*/ */
Mergesort.prototype.sort = function(arr, start, end) { MergeSort.prototype.sort = function(arr, start, end) {
if (arr.length === 0) { if (arr.length === 0) {
return arr; return arr;
} }
@ -51,7 +51,7 @@ Mergesort.prototype.sort = function(arr, start, end) {
/** /**
* *
*/ */
Mergesort.prototype.merge = function(arr1, arr2) { MergeSort.prototype.merge = function(arr1, arr2) {
var result = []; var result = [];
while (arr1.length > 0 || arr2.length > 0) { while (arr1.length > 0 || arr2.length > 0) {

@ -1,16 +1,16 @@
/** /**
* *
*/ */
var Quicksort = function() { var QuickSort = function() {
this.instructions = []; this.instructions = [];
}; };
Quicksort.prototype = Object.create(Sorter.prototype); QuickSort.prototype = Object.create(Sorter.prototype);
/** /**
* *
*/ */
Quicksort.prototype.addInstruction = function(operation, left, right, pivot) { QuickSort.prototype.addInstruction = function(operation, left, right, pivot) {
this.instructions.push({ this.instructions.push({
operation: operation, operation: operation,
left: left, left: left,
@ -23,12 +23,10 @@ Quicksort.prototype.addInstruction = function(operation, left, right, pivot) {
/** /**
* *
*/ */
Quicksort.prototype.sort = function(arr, start, end) { QuickSort.prototype.sort = function(arr, start, end) {
if (end - start <= 0) { if (end - start <= 0) {
this.addInstruction('single', start, end, null); this.addInstruction('single', start, end, null);
return this.visualizer; return arr;
} }
var left = start; var left = start;
@ -66,4 +64,6 @@ Quicksort.prototype.sort = function(arr, start, end) {
this.sort(arr, start, right); this.sort(arr, start, right);
this.sort(arr, left, end); this.sort(arr, left, end);
return arr;
}; };

@ -1,16 +1,16 @@
/** /**
* *
*/ */
var Selectionsort = function() { var SelectionSort = function() {
this.instructions = []; this.instructions = [];
}; };
Selectionsort.prototype = Object.create(Sorter.prototype); SelectionSort.prototype = Object.create(Sorter.prototype);
/** /**
* *
*/ */
Selectionsort.prototype.sort = function(arr) { SelectionSort.prototype.sort = function(arr) {
var len = arr.length; var len = arr.length;
var i; var i;
var j; var j;
@ -36,5 +36,5 @@ Selectionsort.prototype.sort = function(arr) {
} }
} }
console.info(`swaps: ${swaps}, comparisons: ${comparisons} `); // console.info(`swaps: ${swaps}, comparisons: ${comparisons} `);
}; };

@ -1,16 +1,16 @@
/** /**
* *
*/ */
var Shellsort = function() { var ShellSort = function() {
this.instructions = []; this.instructions = [];
}; };
Shellsort.prototype = Object.create(Sorter.prototype); ShellSort.prototype = Object.create(Sorter.prototype);
/** /**
* *
*/ */
Shellsort.prototype.sort = function(arr) { ShellSort.prototype.sort = function(arr) {
var len = arr.length; var len = arr.length;
var gap = Math.floor(len / 3); var gap = Math.floor(len / 3);
var i, j; var i, j;
@ -19,31 +19,31 @@ Shellsort.prototype.sort = function(arr) {
this.gapSort(arr, i, gap); this.gapSort(arr, i, gap);
} }
var IS = new Insertionsort(); var IS = new InsertionSort();
IS.sort(arr); IS.sort(arr);
}; };
/** /**
* *
*/ */
Shellsort.prototype.gapSort = function(arr, start, gap) { ShellSort.prototype.gapSort = function(arr, start, gap) {
var i, j; var i, j;
var len = arr.length; var len = arr.length;
console.log(`start ${start}, gap ${gap}`) // console.log(`start ${start}, gap ${gap}`)
for (i = start; i < len; i += gap) { for (i = start; i < len; i += gap) {
console.log(`i: ${i}`) // console.log(`i: ${i}`)
for (j = i; j > start; j -= gap) { for (j = i; j > start; j -= gap) {
console.log(`j: ${j}`) // console.log(`j: ${j}`)
console.log(`checking if ${arr[j - gap].value} > ${arr[j].value}`) // console.log(`checking if ${arr[j - gap].value} > ${arr[j].value}`)
if (arr[j - gap].value > arr[j].value) { if (arr[j - gap].value > arr[j].value) {
console.log(`swapping ${arr[j - gap].value} and ${arr[j].value}`) // console.log(`swapping ${arr[j - gap].value} and ${arr[j].value}`)
tmp = arr[j - gap]; tmp = arr[j - gap];
arr[j - gap] = arr[j]; arr[j - gap] = arr[j];
arr[j] = tmp; arr[j] = tmp;
console.log(dump(arr)); // console.log(dump(arr));
} }
else { else {
break; break;
@ -51,5 +51,5 @@ Shellsort.prototype.gapSort = function(arr, start, gap) {
} }
} }
console.log(dump(arr)); // console.log(dump(arr));
}; };

@ -37,7 +37,7 @@ Sorter.prototype.generate = function(n) {
* *
*/ */
Sorter.prototype.swap = function(arr, i, j) { Sorter.prototype.swap = function(arr, i, j) {
console.info(`swapping ${arr[i].value} and ${arr[j].value}`) // console.info(`swapping ${arr[i].value} and ${arr[j].value}`)
var tmp = arr[i]; var tmp = arr[i];
arr[i] = arr[j]; arr[i] = arr[j];
arr[j] = tmp; arr[j] = tmp;

@ -10,18 +10,56 @@ function Visualizer(parent) {
bottom.className = 'bottom'; bottom.className = 'bottom';
parent.appendChild(bottom); parent.appendChild(bottom);
var range = this.initRange();
parent.querySelector('.bottom').appendChild(range);
var controls = this.initControls(); var controls = this.initControls();
parent.querySelector('.bottom').appendChild(controls); parent.querySelector('.bottom').appendChild(controls);
var comments = this.initComments();
parent.querySelector('.bottom').appendChild(comments);
var range = this.initRange();
parent.querySelector('.bottom').appendChild(range);
this.groups = null; this.groups = null;
this.parent = parent; this.parent = parent;
this.init(10); this.sorter = null;
switch(parent.attributes['data-algorithm'].value) {
case 'quick':
this.sorter = new QuickSort();
break;
case 'merge':
this.sorter = new MergeSort();
break;
case 'selection':
this.sorter = new SelectionSort();
break;
case 'bubble':
this.sorter = new BubbleSort();
break;
case 'insertion':
this.sorter = new InsertionSort();
break;
case 'shell':
this.sorter = new ShellSort();
break;
case 'radix':
this.sorter = new RadixSort();
break;
default:
throw new Error('Unrecognized sort type.');
}
// this.instructions = null; // this.instructions = null;
// this.currentInstruction = 0; // this.currentInstruction = 0;
this.init(10);
}; };
// Public static properties (mutable) // Public static properties (mutable)
@ -34,61 +72,51 @@ Visualizer.itemY = 20;
* *
*/ */
Visualizer.prototype.init = function(n) { Visualizer.prototype.init = function(n) {
// Sorter setup. var data = this.sorter.generate(n);
var QS = new Quicksort(); var shuffled = this.sorter.shuffle(data);
var data = QS.generate(n);
var shuffled = QS.shuffle(data);
var ordered = Object.create(shuffled); var ordered = Object.create(shuffled);
QS.sort(ordered, 0, ordered.length - 1); ordered = this.sorter.sort(ordered, 0, ordered.length - 1);
var x = []
ordered.forEach(function(obj0) {
x.push(obj0.value);
})
console.log(x.join(',')); // console.log(ordered);
// A swap on the dataset will not take effect until after transition is complete, so custom index is required. // var x = []
var n = 0; // ordered.forEach(function(obj0) {
for (i in shuffled) { // x.push(obj0.value);
shuffled[i].index = n++; // })
}
var svg = d3.select(this.parent.querySelector('.top')).append('svg'); // console.log(x.join(','));
this.groups = svg.selectAll('g').data(shuffled).enter().append('g') // // A swap on the dataset will not take effect until after transition is complete, so custom index is required.
.attr('transform', `translate(0, ${Visualizer.itemY})`); // var n = 0;
// for (i in shuffled) {
// shuffled[i].index = n++;
// }
this.groups.append('rect') // var svg = d3.select(this.parent.querySelector('.top')).append('svg');
.attr('height', Visualizer.itemH)
.attr('width', Visualizer.itemW)
.attr('fill', function doFill(d) { return `rgb(0, 0, ${d.value})`; });
this.groups.transition(500) // this.groups = svg.selectAll('g').data(shuffled).enter().append('g')
.attr('transform', function doTransform(d, i) { // .attr('transform', `translate(0, ${Visualizer.itemY})`);
return `translate(${i * (Visualizer.itemW + Visualizer.spacerW)}, ${Visualizer.itemY})`;
});
this.groups.append('text') // this.groups.append('rect')
.text(function t(d) { return d.value; }) // .attr('height', Visualizer.itemH)
.attr('fill', '#aaa') // .attr('width', Visualizer.itemW)
.attr('font-size', 10) // .attr('fill', function doFill(d) { return `rgb(0, 0, ${d.value})`; });
.attr('font-family', 'sans-serif')
.attr('transform', function doTransform(d) {
return `rotate(90 0,0), translate(5, -3)`;
});
// V.addMarker('quicksort-left-marker');
// V.moveMarker('quicksort-left-marker', 2);
// this.svg.append('sometext').id('left-marker'); L
// this.svg.append('sometext').id('right-marker'); R
// this.svg.append('sometext').id('pivot-marker'); triangle or arrow
// this.groups.transition(500)
// .attr('transform', function doTransform(d, i) {
// return `translate(${i * (Visualizer.itemW + Visualizer.spacerW)}, ${Visualizer.itemY})`;
// });
// this.groups.append('text')
// .text(function t(d) { return d.value; })
// .attr('fill', '#aaa')
// .attr('font-size', 10)
// .attr('font-family', 'sans-serif')
// .attr('transform', function doTransform(d) {
// return `rotate(90 0,0), translate(5, -3)`;
// });
setTimeout(this.followInstruction.bind(this, QS.instructions, 0), 500); // setTimeout(this.followInstruction.bind(this, QS.instructions, 0), 500);
}; };
/** /**
@ -113,31 +141,6 @@ Visualizer.prototype.swap = function(indexA, indexB) {
}) })
}; };
/**
*
* /
Visualizer.prototype.moveMarker = function(id, toIndex) {
this.svg.select('#' + id).attr('x', toIndex * 22);
};
/**
*
* /
Visualizer.prototype.addMarker = function(id) {
// this.svg.append('text')
// .attr('id', id)
// .attr('x', 53)
// .attr('y', 50)
// .attr('width', 20)
// .attr('height', 20)
// .attr('fill', '#aaa')
// .attr('font-size', 20)
// .attr('alignment-baseline', 'middle')
// .attr('text-anchor', 'middle')
// .attr('transform', 'rotate(0 53,50)')
// .text('P');
};
/** /**
* *
*/ */
@ -195,11 +198,33 @@ Visualizer.prototype.followInstruction = function(instructions, index) {
} }
}; };
/**
*
*/
Visualizer.prototype.initComments = function() {
var container = document.createElement('div');
container.className = 'comment-container';
var div1 = document.createElement('div');
div1.className = 'comment';
var div2 = document.createElement('div');
div2.className = 'comment';
var div3 = document.createElement('div');
div3.className = 'comment';
container.appendChild(div1);
container.appendChild(div2);
container.appendChild(div3);
return container;
};
/** /**
* *
*/ */
Visualizer.prototype.initRange = function(Visualizer) { Visualizer.prototype.initRange = function() {
var container = document.createElement('div'); var container = document.createElement('div');
container.className = 'range-container'; container.className = 'range-container';
@ -259,7 +284,7 @@ Visualizer.prototype.initControls = function() {
reset.addEventListener('click', onclick); reset.addEventListener('click', onclick);
var container = document.createElement('div'); var container = document.createElement('div');
container.className = 'controls'; container.className = 'controls-container';
container.appendChild(reset); container.appendChild(reset);
container.appendChild(back); container.appendChild(back);

Loading…
Cancel
Save