Most humans when sorting—ordering a deck of cards, for example—use a method that is similar to insertion sort. —Wikipedia - Insertion SortThe obvious lessons:
- Insertion sort is a simple and intuitive algorithm
- The obvious algorithm is sometimes slow
- Humans optimise for human-sized problems
Hang on though, when I sort a deck of cards, I do this:
- Sort 5 cards through some intuitive process.
- Grab another card (if there is one)
- Find where it goes
- Insert it
- Go to step 2
But I certainly don't lay all the sorted cards out in a line, and move them all across by one when I insert one into the list. I just make a gap and stick the card in. This doesn't take longer if i have more cards!
What does take longer is finding the right place to insert a card, but when this gets hard I end up using a modified binary search. (Modified because I know something about the distribution of cards, and because it's easy to look at (and cache) a few consecutive cards). So this is log(n), and the overall algorithm is O(n log n), or as we say in Germany, 'fast'[1].
The ringbinder
We get away from it because real life has a 'data structure' that's half array, half linked list:
- 'Get the nth item' is constant time (ish. You get pretty good at estimating how thick 10 cards are)
- Insert an item is constant time.
- Remove an item is constant time
I'm going to call this structure the 'Ringbinder' because 'Stack' is already taken by something that behaves nothing like any real-life stack I've ever seen. For sufficiently large values of N, your program will run faster using a USB robotic ring-binder operator rather than an ArrayList. You heard it here first.
Divserion: quantum bogosort
Cheating at algorithms using real-life's weirdnesses isn't new. qfork() is a version of fork() that returns a different value in each quantum universe. So we sort in O(n) like so:
srand(qfork()); shuffle(data); if(!sorted(data)) exit(1); // todo cleanup world
I mention this only because it amuses me.
So, seriously?
I guess at some point physically moving the cards to make a gap doesn't actually take constant time. If our robot can exert some fixed force and has to move n items just enough to make room for one more, then this takes O(√n) time[2]. Revised performance:
- Go to index: O(√n)
- Get next/prev: O(1)
- Insert/delete: O(1)
This makes our insertion sort O(n^1.5 log n) which is no longer state of the art. But surely there are currently-optimal algorithms where using this data structure would give better asymptotic performance than we get on our fancy-pants von Neumann machines[3]. Or maybe I'm missing something. I'm probably missing something.
Any others?
What other data structures can you build from common household items that put our silicon masters to shame when it comes to data processing?
(Using people to demonstrate the power of parallelism doesn't count, It's been done).
[1] working for American software companies is a lousy way to learn German.
[2] F=ma, s = at^2, etc.
[3] and way worse real-world performance, as we're shoveling around avocado-sized chunks of matter instead of deftly handling individual atoms. Still.




