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

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

@ -1,16 +1,16 @@
/**
*
*/
var Insertionsort = function() {
var InsertionSort = function() {
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 i;
var j;

@ -1,22 +1,22 @@
/**
*
*/
var Mergesort = function() {
var MergeSort = function() {
this.instructions = [];
};
Mergesort.prototype = Object.create(Sorter.prototype);
MergeSort.prototype = Object.create(Sorter.prototype);
/**
*
*/
Mergesort.prototype.addInstruction = function(operation, left, right, mid) {
console.log({
operation: operation,
left: left,
right: right,
mid: mid
});
MergeSort.prototype.addInstruction = function(operation, left, right, mid) {
// console.log({
// operation: operation,
// left: left,
// right: right,
// mid: mid
// });
this.instructions.push({
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) {
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 = [];
while (arr1.length > 0 || arr2.length > 0) {

@ -1,16 +1,16 @@
/**
*
*/
var Quicksort = function() {
var QuickSort = function() {
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({
operation: operation,
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) {
this.addInstruction('single', start, end, null);
return this.visualizer;
return arr;
}
var left = start;
@ -66,4 +64,6 @@ Quicksort.prototype.sort = function(arr, start, end) {
this.sort(arr, start, right);
this.sort(arr, left, end);
return arr;
};

@ -1,16 +1,16 @@
/**
*
*/
var Selectionsort = function() {
var SelectionSort = function() {
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 i;
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 = [];
};
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 gap = Math.floor(len / 3);
var i, j;
@ -19,31 +19,31 @@ Shellsort.prototype.sort = function(arr) {
this.gapSort(arr, i, gap);
}
var IS = new Insertionsort();
var IS = new InsertionSort();
IS.sort(arr);
};
/**
*
*/
Shellsort.prototype.gapSort = function(arr, start, gap) {
ShellSort.prototype.gapSort = function(arr, start, gap) {
var i, j;
var len = arr.length;
console.log(`start ${start}, gap ${gap}`)
// console.log(`start ${start}, gap ${gap}`)
for (i = start; i < len; i += gap) {
console.log(`i: ${i}`)
// console.log(`i: ${i}`)
for (j = i; j > start; j -= gap) {
console.log(`j: ${j}`)
console.log(`checking if ${arr[j - gap].value} > ${arr[j].value}`)
// console.log(`j: ${j}`)
// console.log(`checking 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];
arr[j - gap] = arr[j];
arr[j] = tmp;
console.log(dump(arr));
// console.log(dump(arr));
}
else {
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) {
console.info(`swapping ${arr[i].value} and ${arr[j].value}`)
// console.info(`swapping ${arr[i].value} and ${arr[j].value}`)
var tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;

@ -10,18 +10,56 @@ function Visualizer(parent) {
bottom.className = 'bottom';
parent.appendChild(bottom);
var range = this.initRange();
parent.querySelector('.bottom').appendChild(range);
var controls = this.initControls();
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.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.currentInstruction = 0;
this.init(10);
};
// Public static properties (mutable)
@ -34,61 +72,51 @@ Visualizer.itemY = 20;
*
*/
Visualizer.prototype.init = function(n) {
// Sorter setup.
var QS = new Quicksort();
var data = QS.generate(n);
var shuffled = QS.shuffle(data);
var data = this.sorter.generate(n);
var shuffled = this.sorter.shuffle(data);
var ordered = Object.create(shuffled);
QS.sort(ordered, 0, ordered.length - 1);
var x = []
ordered.forEach(function(obj0) {
x.push(obj0.value);
})
ordered = this.sorter.sort(ordered, 0, ordered.length - 1);
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 n = 0;
for (i in shuffled) {
shuffled[i].index = n++;
}
// var x = []
// ordered.forEach(function(obj0) {
// x.push(obj0.value);
// })
var svg = d3.select(this.parent.querySelector('.top')).append('svg');
// console.log(x.join(','));
this.groups = svg.selectAll('g').data(shuffled).enter().append('g')
.attr('transform', `translate(0, ${Visualizer.itemY})`);
// // A swap on the dataset will not take effect until after transition is complete, so custom index is required.
// var n = 0;
// for (i in shuffled) {
// shuffled[i].index = n++;
// }
this.groups.append('rect')
.attr('height', Visualizer.itemH)
.attr('width', Visualizer.itemW)
.attr('fill', function doFill(d) { return `rgb(0, 0, ${d.value})`; });
// var svg = d3.select(this.parent.querySelector('.top')).append('svg');
this.groups.transition(500)
.attr('transform', function doTransform(d, i) {
return `translate(${i * (Visualizer.itemW + Visualizer.spacerW)}, ${Visualizer.itemY})`;
});
// this.groups = svg.selectAll('g').data(shuffled).enter().append('g')
// .attr('transform', `translate(0, ${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)`;
});
// 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.append('rect')
// .attr('height', Visualizer.itemH)
// .attr('width', Visualizer.itemW)
// .attr('fill', function doFill(d) { return `rgb(0, 0, ${d.value})`; });
// 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');
container.className = 'range-container';
@ -259,7 +284,7 @@ Visualizer.prototype.initControls = function() {
reset.addEventListener('click', onclick);
var container = document.createElement('div');
container.className = 'controls';
container.className = 'controls-container';
container.appendChild(reset);
container.appendChild(back);

Loading…
Cancel
Save