Skip to content

Instantly share code, notes, and snippets.

@oxyflour
Created March 4, 2017 05:28
Show Gist options
  • Select an option

  • Save oxyflour/da3f115960a9bf506d88f8ddcd8dda71 to your computer and use it in GitHub Desktop.

Select an option

Save oxyflour/da3f115960a9bf506d88f8ddcd8dda71 to your computer and use it in GitHub Desktop.
Sorting Algorithm Animations
<body>
<script>
// https://github.com/vbohush/SortingAlgorithmAnimations
const methods = {
async bubble(a) {
// https://en.wikipedia.org/wiki/Bubble_sort
for (let i = 0; i < a.length; i ++) {
for (let j = a.length - 1; j > i; j --) {
if (await a.comp(a[j - 1], a[j])) {
a.swap(j - 1, j)
}
}
}
},
async selection(a) {
// https://en.wikipedia.org/wiki/Selection_sort
for (let i = 0; i < a.length - 1; i ++) {
let m = i
for (let j = i + 1; j < a.length; j ++) {
if (await a.comp(a[m], a[j])) {
m = j
}
}
if (m !== i) {
a.swap(m, i)
}
}
},
async insertion(a) {
// https://en.wikipedia.org/wiki/Insertion_sort
for (let i = 1; i < a.length; i ++) {
let j = i
while (j > 0 && (await a.comp(a[j - 1], a[j]))) {
a.swap(j - 1, j)
j --
}
}
},
async quicksort(a) {
// https://en.wikipedia.org/wiki/Quicksort
async function sort(lo, hi) {
if (lo < hi) {
const p = await part(lo, hi)
await sort(lo, p - 1)
await sort(p + 1, hi)
}
}
async function part(lo, hi) {
const p = a[hi]
let i = lo - 1
for (let j = lo; j < hi; j ++) {
if (await a.comp(p, a[j])) {
i ++
a.swap(i, j)
}
}
a.swap(i + 1, hi)
return i + 1
}
await sort(0, a.length - 1)
}
}
Array.prototype.swap = function(i, j) {
[this[i], this[j]] = [this[j], this[i]]
return this
}
Array.prototype.shuffle = function() {
this.forEach((v, i) => this.swap(i, Math.floor(Math.random() * (this.length - i))))
return this
}
Array.prototype.drawTo = function(canvas) {
const dc = canvas.getContext('2d')
dc.clearRect(0, 0, canvas.width, canvas.height)
dc.lineWidth = canvas.width / this.length
const min = Math.min.apply(Math, this),
max = Math.max.apply(Math, this)
this.forEach((v, i) => {
const f = (v - min) / (max - min),
x = dc.lineWidth * (i + 0.5)
dc.strokeStyle = `hsl(${f * 360}, 100%, 50%)`
dc.beginPath()
dc.moveTo(x, 0)
dc.lineTo(x, canvas.height)
dc.closePath()
dc.stroke()
})
}
function el(tag, attrs, children) {
const elem = Object.assign(document.createElement(tag), attrs)
children && children.forEach(child => elem.appendChild(child))
return elem
}
function range(n) {
return Array(n).fill(0).map((_, i) => i)
}
function nextFrame(fn) {
return new Promise(resolve => requestAnimationFrame(_ => fn(resolve)))
}
; [
['shuffled', range(50).shuffle()],
['ordered', range(50)],
['reversed', range(50).reverse()],
].forEach(([name, array]) => {
let elem
document.body.appendChild(el('div', { }, [
el('h1', { innerHTML: name }),
elem = el('div')
]))
Object.keys(methods).forEach(name => {
let canvas, span, count = 0
elem.appendChild(el('div', { }, [
el('div', { }, [
el('span', { innerHTML: name + ': ' }),
span = el('span'),
]),
canvas = el('canvas', { width: 500, height: 20 }),
]))
const arr = array.slice()
arr.drawTo(canvas)
arr.swap = (i, j) => [].swap.call(arr, i, j).drawTo(canvas)
arr.comp = (a, b) => nextFrame(resolve => (span.innerHTML = ++ count) && resolve(a > b))
methods[name](arr)
})
})
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment