Finalizing discussion points.

master
ben-burlingham 10 years ago
parent 35303a9bc9
commit 1fdee61243
  1. 11
      css/style.css
  2. 228
      index.html
  3. 6
      js/itemgroup.js
  4. 1
      js/sorter.js
  5. 6
      js/visualizer-dom.js
  6. 10
      js/visualizer.js

@ -1,3 +1,13 @@
.src {
display:block;
font-size:14px;
margin:10px 0;
}
.title {
font-weight:bold;
}
.sorter { .sorter {
background:#f4f4f4; background:#f4f4f4;
border:1px solid #bbb; border:1px solid #bbb;
@ -38,6 +48,7 @@
.sorter-properties { .sorter-properties {
height:40px; height:40px;
left:10px; left:10px;
line-height:normal;
position:absolute; position:absolute;
top:210px; top:210px;
width:570px; width:570px;

@ -14,109 +14,220 @@
Here are visualizations of common sorting algorithms. Use the comparisons counter Here are visualizations of common sorting algorithms. Use the comparisons counter
and number of items to observe the performance of each randomized case. and number of items to observe the performance of each randomized case.
<a href='http://gogs.benburlingham.com/ben.burlingham/d3-sort-visualization' target='_new'>[Source repository]</a> <br><br>
<br>
All source data is shuffled using the <a href='http://bost.ocks.org/mike/algorithms/'>Fisher-Yates</a> algorithm.
<br><br>
There's a fun clip about the sounds of sorting <a href="https://www.youtube.com/watch?v=t8g-iYGHpEA">here</a>.
<br><br>
<h2>Quick sort discussion</h2>
<a class='src' href='http://gogs.benburlingham.com/ben.burlingham/d3-sort-visualization/src/master/js/quicksort.js'>Source Code</a>
<p>
<span class='title'>Implementation</span>
<ul>
<li>Select a pivot element anywhere in the list</li>
<li>Uses "left" and "right" markers that approach each other from opposite ends of the list</li>
<li>Left marker halts if its current value is greater than pivot</li>
<li>Right marker halts if its current value is less than pivot</li>
<li>Swap after both markers are halted, then continue moving inwards</li>
<li>Once markers pass eachother, recurse for sublists on each side of pivot</li>
</ul>
</p>
<h2>Quicksort discussion</h2>
<p> <p>
used by chrome.<br> <span class='title'>Notes</span>
source code link <ul>
<li>"Conquer and divide" algorithm</li>
<li>Performance depends heavily on pivot selection</li>
<li>O(n) time possible with partitioning</li>
</ul>
</p> </p>
<div class="sorter" <div class="sorter"
data-algorithm='quick' data-algorithm='quick'
data-stable='Maybe' data-stable='No'
data-adaptive='Maybe' data-adaptive='No'
data-worst-perf='O(n + m + 3k)' data-worst-perf='O (n^2)'
data-avg-perf='O(n + m + 3k)' data-avg-perf='O (n log n)'
data-best-perf='O(n + m + 3k)' data-best-perf='O (n log n)'
data-worst-memory='0 (in place)' data-worst-memory='0'
></div> ></div>
<h2>Mergesort discussion</h2> <h2>Merge sort discussion</h2>
<a class='src' href='http://gogs.benburlingham.com/ben.burlingham/d3-sort-visualization/src/master/js/mergesort.js'>Source Code</a>
<p>
<span class='title'>Implementation</span>
<ul>
<li>Recursively split array until only single element slices remain.</li>
<li>Consider two slices. Compare their heads and unshift minimum into a result array.</li>
<li>Continue comparing heads and unshifting until the two slices are empty.</li>
<li>Build result arrays from all the slices.</li>
<li>Recurse the comparison process on the result arrays.</li>
</ul>
</p>
<p> <p>
used by firefox and safari.<br> <span class='title'>Notes</span>
helpful: http://stackoverflow.com/questions/2967153/space-requirements-of-a-merge-sort<br> <ul>
source code link <li>Top down variant: Recursively split into halves, sort halves depth first, ending with original two halves. Tree-like. Implemented here.</li>
<li>Bottom up variant: Split fixed intervals, sort each interval, join into full array, split larger interval, repeat.</li>
<li>Natural variant: Bottom up, but with adaptive interval selection over existing ordering.</li>
<li><a href="http://stackoverflow.com/questions/10153393/mergesort-is-bottom-up-faster-than-top-down">Discussion of variants</a></li>
</ul>
</p> </p>
<div class="sorter" <div class="sorter"
data-algorithm='merge' data-algorithm='merge'
data-stable='Maybe' data-stable='Yes'
data-adaptive='Maybe' data-adaptive='Yes'
data-worst-perf='O(n + m + 3k)' data-worst-perf='O (n log n)'
data-avg-perf='O(n + m + 3k)' data-avg-perf='O (n log n)'
data-best-perf='O(n + m + 3k)' data-best-perf='O (n log n)'
data-worst-memory='0 (in place)' data-worst-memory='O (n)'
></div> ></div>
<h2>Selection sort discussion</h2> <h2>Selection sort discussion</h2>
<a class='src' href='http://gogs.benburlingham.com/ben.burlingham/d3-sort-visualization/src/master/js/selectionsort.js'>Source Code</a>
<p>
<span class='title'>Implementation</span>
<ul>
<li>Consider [0]. Compare it to the rest of the elements to find the minimum value.</li>
<li>Swap [0] with the index of the minimum. [0] is now finished.</li>
<li>Proceed to [1]. Repeat.</li>
</ul>
</p>
<p> <p>
http://stackoverflow.com/questions/15799034/insertion-sort-vs-selection-sort <br> <span class='title'>Notes</span>
finds upstram minimum and swaps with current.<br> <ul>
source code link <li>To remember: selection sort selects the minimum.</li>
<li>Be aware of the unstable version, where a swap is greedy.</li>
<li>No other sorting algorithm has less data movement (<a href="http://rosettacode.org/wiki/Sorting_algorithms/Selection_sort">Rosetta Code</a>)</li>
<li>Good for cases where writes are expensive.</li>
</ul>
</p> </p>
<div class="sorter" <div class="sorter"
data-algorithm='selection' data-algorithm='selection'
data-stable='Maybe' data-stable='Yes'
data-adaptive='Maybe' data-adaptive='No'
data-worst-perf='O(n + m + 3k)' data-worst-perf='O (n^2)'
data-avg-perf='O(n + m + 3k)' data-avg-perf='O (n^2)'
data-best-perf='O(n + m + 3k)' data-best-perf='O (n^2)'
data-worst-memory='0 (in place)'> data-worst-memory='0'>
</div> </div>
<h2>Insertion sort discussion</h2> <h2>Insertion sort discussion</h2>
<a class='src' href='http://gogs.benburlingham.com/ben.burlingham/d3-sort-visualization/src/master/js/insertionsort.js'>Source Code</a>
<p> <p>
how is this different from bubble and selection. <br> <span class='title'>Implementation</span>
swap. highlight. fade.<br> <ul>
source code link <li>Compare [1] and [0]. Swap if [0] > [1].</li>
<li>Compare [2] and [1]. Swap if needed. Continue swapping downward one by one until no swap is needed.</li>
<li>Repeat with [3], [4], etc. until end of the array.</li>
</ul>
</p>
<p>
<span class='title'>Notes</span>
<ul>
<li>Simplicity can make insertion sort a good choice for small arrays.</li>
<li>Similar to selection sort, but uses bubbling rather than minimums.</li>
</ul>
</p> </p>
<div class="sorter" <div class="sorter"
data-algorithm='insertion' data-algorithm='insertion'
data-stable='Maybe' data-stable='Yes'
data-adaptive='Maybe' data-adaptive='Yes'
data-worst-perf='O(n + m + 3k)' data-worst-perf='O (n^2)'
data-avg-perf='O(n + m + 3k)' data-avg-perf='O (n^2)'
data-best-perf='O(n + m + 3k)' data-best-perf='O (n)'
data-worst-memory='0 (in place)' data-worst-memory='0'
></div> ></div>
<h2>Shellsort discussion</h2> <h2>Shellsort discussion</h2>
<a class='src' href='http://gogs.benburlingham.com/ben.burlingham/d3-sort-visualization/src/master/js/shellsort.js'>Source Code</a>
<p>
<span class='title'>Implementation</span>
<ul>
<li>Decide on a gap width. 3 is used here.</li>
<li>Start at [3]. Compare to [0]. Swap if [0] > [3].</li>
<li>Move to [4]. Compare to [1]. Swap if necessary.</li>
<li>Move to [5]. Compare to [2]. Swap if necessary.</li>
<li>Continue the pattern and bubble downstream, exactly like insertion sort but with a gap of 3, not 1.</li>
<li>After the end of the list is reached, it is weakly sorted. Perform a final insertion sort.</li>
<li>Note: Insertion sort is a shell sort with a gap of 1.</li>
</ul>
</p>
<p> <p>
several ways to pick gap width, but dependence on input data makes gap selection trivial.<br> <span class='title'>Notes</span>
Insertion sort with gap of 1.<br> <ul>
source code link <li>Weakly sorts elements to prepare for final pass using different sort algorithm</li>
<li>Average performance depends on gap selection, but...</li>
<li>Dependence on input data makes gap selection highly subjective</li>
</ul>
</p> </p>
<div class="sorter" <div class="sorter"
data-algorithm='shell' data-algorithm='shell'
data-stable='Maybe' data-stable='No'
data-adaptive='Maybe' data-adaptive='Yes'
data-worst-perf='O(n + m + 3k)' data-worst-perf='O (n^2)'
data-avg-perf='O(n + m + 3k)' data-avg-perf='-'
data-best-perf='O(n + m + 3k)' data-best-perf='O (n lg n)'
data-worst-memory='0 (in place)' data-worst-memory='n'
></div> ></div>
<h2>Bubble sort discussion</h2> <h2>Bubble sort discussion</h2>
<a class='src' href='http://gogs.benburlingham.com/ben.burlingham/d3-sort-visualization/src/master/js/bubblesort.js'>Source Code</a>
<p>
<span class='title'>Implementation</span>
<ul>
<li>Order [1] and [0].</li>
<li>Order [2] and [1].</li>
<li>Continue to the end. Note that there is at most one swap per index.</li>
<li>Repeat the process until fully ordered. Keep a boolean that shows if swaps have been made.</li>
<li>Once there is a pass without swaps, all elements have bubbled down to their proper positions.</li>
</ul>
</p>
<p> <p>
how is this different from insertion and selection sorts. <br> <span class='title'>Notes</span>
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> <ul>
source code link <li>If even one number is out of place means a new pass must be done.</li>
<li>"Turtles" are small values that crawl slowly toward their position near the front.</li>
<li>"Rabbits" are large values that hop quickly to their position near the end.</li>
<li>Variations on bubble sort (cocktail sort, comb sort) try to address the turtle problem.</li>
</ul>
</p> </p>
<div class="sorter" <div class="sorter"
data-algorithm='bubble' data-algorithm='bubble'
data-stable='Maybe' data-stable='Yes'
data-adaptive='Maybe' data-adaptive='Yes'
data-worst-perf='O(n + m + 3k)' data-worst-perf='O (n^2)'
data-avg-perf='O(n + m + 3k)' data-avg-perf='O (n^2)'
data-best-perf='O(n + m + 3k)' data-best-perf='O (n)'
data-worst-memory='0 (in place)' data-worst-memory='0'
></div> ></div>
<!-- <!--
@ -178,3 +289,4 @@
</script> </script>
</body> </body>
</html> </html>
O (n)

@ -47,11 +47,6 @@ var Itemgroup = {
var x, a, b; var x, a, b;
var len = group.selectAll('g')[0].length; var len = group.selectAll('g')[0].length;
// NOTE pitfalls in the swapping problem.
// NOTE Two way binding here between dataset and function parameter?
// NOTE swapping will not reorder index and i parameter will be off
// NOTE discuss chained transitions: http://bl.ocks.org/mbostock/1125997
// Animate a node swap which will be quietly undone after completion. // Animate a node swap which will be quietly undone after completion.
group.selectAll('g').transition().duration(delay - 100) group.selectAll('g').transition().duration(delay - 100)
.attr('transform', function transform(d, i) { .attr('transform', function transform(d, i) {
@ -120,7 +115,6 @@ var Itemgroup = {
* *
*/ */
text: function text(group, delay, which, text) { text: function text(group, delay, which, text) {
// NOTE http://stackoverflow.com/questions/28390754/get-one-element-from-d3js-selection-by-index
group.selectAll('g') group.selectAll('g')
.filter(function filter(d, i) { return i === which; }) .filter(function filter(d, i) { return i === which; })
.select('text').text(text); .select('text').text(text);

@ -10,7 +10,6 @@ var Sorter = function() {
this.comparisons = []; this.comparisons = [];
}; };
// NOTE fisher-yates, http://bost.ocks.org/mike/algorithms/
/** /**
* Returns copy of an array shuffled using Fisher-Yates. * Returns copy of an array shuffled using Fisher-Yates.
*/ */

@ -207,7 +207,7 @@ Visualizer.prototype.initProperties = function() {
div3.className = 'property p3'; div3.className = 'property p3';
var title3 = document.createElement('div'); var title3 = document.createElement('div');
title3.innerHTML = 'Worst Performance'; title3.innerHTML = 'Worst Perf.';
title3.className = 'title'; title3.className = 'title';
div3.appendChild(title3); div3.appendChild(title3);
@ -221,7 +221,7 @@ Visualizer.prototype.initProperties = function() {
div4.className = 'property p4'; div4.className = 'property p4';
var title4 = document.createElement('div'); var title4 = document.createElement('div');
title4.innerHTML = 'Avg Performance'; title4.innerHTML = 'Avg Perf.';
title4.className = 'title'; title4.className = 'title';
div4.appendChild(title4); div4.appendChild(title4);
@ -235,7 +235,7 @@ Visualizer.prototype.initProperties = function() {
div5.className = 'property p5'; div5.className = 'property p5';
var title5 = document.createElement('div'); var title5 = document.createElement('div');
title5.innerHTML = 'Best Performance'; title5.innerHTML = 'Best Perf.';
title5.className = 'title'; title5.className = 'title';
div5.appendChild(title5); div5.appendChild(title5);

@ -102,16 +102,10 @@ Visualizer.prototype.go = function() {
action[0].apply(this, args); action[0].apply(this, args);
// TODO add links to stats
// TODO heap sort // TODO heap sort
// TODO radix sort // TODO radix sort
// TODO in quicksort, change color or element that is in final position // TODO comb sort
// TODO cocktail sort
// NOTE functional programming discussion
// NOTE interesting (anti?)pattern here.
// NOTE use of call() vs apply() (apply only delivered first array item as string)
// if (typeof operation === 'function') {
// operation.call(this, action);
if (delay === 0) { if (delay === 0) {
this.actionIndex++; this.actionIndex++;

Loading…
Cancel
Save