|
|
|
@ -5,17 +5,176 @@ |
|
|
|
|
<title>D3</title> |
|
|
|
|
|
|
|
|
|
<script type='text/javascript' src='vendor/d3/d3.min.js'></script> |
|
|
|
|
<style type='text/css'></style> |
|
|
|
|
<style type='text/css'> |
|
|
|
|
html, body { |
|
|
|
|
margin:0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.quicksort-random { |
|
|
|
|
display:block; |
|
|
|
|
height:60px; |
|
|
|
|
margin:0 auto; |
|
|
|
|
width:1198px; |
|
|
|
|
} |
|
|
|
|
</style> |
|
|
|
|
</head> |
|
|
|
|
<body> |
|
|
|
|
<script type='text/javascript'> |
|
|
|
|
var dataset = [ 5, 10, 15, 20, 25 ]; |
|
|
|
|
var swatchH = 50; |
|
|
|
|
var swatchW = 10; |
|
|
|
|
var dataset = []; |
|
|
|
|
|
|
|
|
|
// TODO namespace this |
|
|
|
|
(function populate() { |
|
|
|
|
var len = 100; |
|
|
|
|
var r, g, b; |
|
|
|
|
for (var i = 0; i < len; i++) { |
|
|
|
|
dataset.push({ |
|
|
|
|
x: 0, |
|
|
|
|
y: 20, |
|
|
|
|
r: 0, //Math.floor((len - i) * 255 / len), |
|
|
|
|
g: 0, |
|
|
|
|
b: Math.floor(i * 255 / len) |
|
|
|
|
}); |
|
|
|
|
}; |
|
|
|
|
}()); |
|
|
|
|
|
|
|
|
|
dataset = shuffle(dataset); |
|
|
|
|
|
|
|
|
|
var svg = d3.select('body').append('svg') |
|
|
|
|
.attr('class', 'quicksort-random'); |
|
|
|
|
|
|
|
|
|
var rectangles = svg.selectAll('rect') |
|
|
|
|
.data(dataset).enter() |
|
|
|
|
.append('rect') |
|
|
|
|
.attr('height', swatchH) |
|
|
|
|
.attr('width', swatchW) |
|
|
|
|
// .attr('') |
|
|
|
|
.attr('fill', function fill(d) { |
|
|
|
|
return `rgb(${d.r}, ${d.g}, ${d.b})`; |
|
|
|
|
}) |
|
|
|
|
.attr('y', function y(d) { return d.y; }) |
|
|
|
|
.attr('x', function x(d) { return d.x; }) |
|
|
|
|
.transition(500) |
|
|
|
|
.attr('x', function xb(d, i) { |
|
|
|
|
dataset[i].x = i * (swatchW + 2); |
|
|
|
|
return dataset[i].x; |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
function visualSwap(indexA, indexB) { |
|
|
|
|
// Move up |
|
|
|
|
// NOTE Two way binding here between dataset and function parameter |
|
|
|
|
rectangles |
|
|
|
|
.transition() |
|
|
|
|
.duration(100) |
|
|
|
|
.attr('y', function ya(d, i) { |
|
|
|
|
if (i === indexA || i === indexB) { |
|
|
|
|
dataset[i].y = 5; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return dataset[i].y; // NOTE d[i].y has been modified too. But, the bound value in the dataset |
|
|
|
|
// will not be updated until after the chain is completed, so it has to be explicitly defined here. |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
// Switch places |
|
|
|
|
// NOTE discuss chained transitions: http://bl.ocks.org/mbostock/1125997 |
|
|
|
|
.transition() |
|
|
|
|
.duration(500) |
|
|
|
|
.attr('x', function xa(d, i) { |
|
|
|
|
if (i === indexA) { |
|
|
|
|
var tmp = dataset[indexA].x; |
|
|
|
|
dataset[indexA].x = dataset[indexB].x; |
|
|
|
|
dataset[indexB].x = tmp; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return d.x; |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
// Move down |
|
|
|
|
.transition() |
|
|
|
|
.duration(100) |
|
|
|
|
.attr('y', function ya(d, i) { |
|
|
|
|
if (i === indexA || i === indexB) { |
|
|
|
|
dataset[i].y = 20; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return dataset[i].y; |
|
|
|
|
}) |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
function highlight(index) { |
|
|
|
|
svg.selectAll('rect') |
|
|
|
|
.attr('stroke', function(d, i) { if (i === index) { return 'lime'; } }) |
|
|
|
|
.attr('stroke-width', function(d, i) { if (i === index) { return 4; } }); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
function unhighlightAll(index) { |
|
|
|
|
svg.selectAll('rect') |
|
|
|
|
.attr('stroke', function(d, i) { return null; }) |
|
|
|
|
.attr('stroke-width', function(d, i) { return null; }); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// NOTE fisher-yates, http://bost.ocks.org/mike/algorithms/ |
|
|
|
|
function shuffle(arr) { |
|
|
|
|
var n = arr.length, t, i; |
|
|
|
|
while (n) { |
|
|
|
|
i = Math.random() * n-- | 0; // 0 ≤ i < n |
|
|
|
|
t = arr[n]; |
|
|
|
|
arr[n] = arr[i]; |
|
|
|
|
arr[i] = t; |
|
|
|
|
} |
|
|
|
|
return arr; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// visualSwap(0, 1); |
|
|
|
|
|
|
|
|
|
function quicksort(arr, startIndex, endIndex) { |
|
|
|
|
if (endIndex - startIndex <= 0) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var left = startIndex; |
|
|
|
|
var right = endIndex; |
|
|
|
|
|
|
|
|
|
unhighlightAll(); |
|
|
|
|
var pivotIndex = Math.floor((right + left) / 2); |
|
|
|
|
var pval = arr[pivotIndex].b; |
|
|
|
|
var tmp; |
|
|
|
|
highlight(pivotIndex); |
|
|
|
|
|
|
|
|
|
while (left <= right) { |
|
|
|
|
while (arr[left].b < pval) { |
|
|
|
|
left++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
while (arr[right].b > pval) { |
|
|
|
|
right--; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (left <= right) { |
|
|
|
|
tmp = arr[left]; |
|
|
|
|
arr[left] = arr[right]; |
|
|
|
|
arr[right] = tmp; |
|
|
|
|
visualSwap(left, right); |
|
|
|
|
|
|
|
|
|
left++; |
|
|
|
|
right--; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
quicksort(arr, startIndex, right); |
|
|
|
|
quicksort(arr, left, endIndex); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
quicksort(dataset, 0, dataset.length - 1); |
|
|
|
|
console.error(dataset); |
|
|
|
|
|
|
|
|
|
// var instructions = []; |
|
|
|
|
// instructions.push('M ' + (50 * i) + ',50'); |
|
|
|
|
// instructions.push('A 50,50 0 0,1 ' + (50 * (i + 1)) + ',0'); |
|
|
|
|
// instructions.push('L ' + (50 * (i + 1)) + ',50'); |
|
|
|
|
// instructions.push('L ' + (50 * i) + ',50'); |
|
|
|
|
|
|
|
|
|
d3.select("body").selectAll("p") |
|
|
|
|
.data(dataset) |
|
|
|
|
.enter() |
|
|
|
|
.append("p") |
|
|
|
|
.text(function(d) { return d; }); |
|
|
|
|
</script> |
|
|
|
|
</body> |
|
|
|
|
</html> |
|
|
|
|