WikiSort – Fast, stable, O(1) space merge sort algorithm
github.com
github.com
This particular implementation (looking at the C version) uses fixed-size 'long ints' for its temporary data storage, which means it only works on arrays up to LONG_MAX elements. If you had larger arrays, your need for temporary data would grow, e.g. you could upgrade all those long ints to long long ints and accommodate arrays up to LLONG_MAX. Of course, logarithmic growth is very slow.
The two things you can do are: 1) pick a fixed-size int and cap the max size of array you can handle; or 2) use a bigint datatype, and the size of your bigints will (asymptotically) grow with log(n).
Edit: A comment above claims that without this bound, quicksort isn't even log n space.
If your temporary space was used by some indices represented as unary-encoded integers (which take O(n) space), it'd suddenly be harder to ignore the indices, because O(n) is not "very small" for many commonly encountered sizes of n. So I don't think taking the temporary space used by indexing into account is conceptually wrong, it just happens not to matter here because log(n) factors often don't matter.
http://googleresearch.blogspot.ca/2006/06/extra-extra-read-a...
If people are using abstract data types and/or built-ins, in practice, presumably they can use a fixed int type for O(1) runtime and just update the data type every 20 years or so.
On that note, has anyone actually created a 2^128 element array yet? I suspect such an array would be too large to represent in the memory of all the world's computers at the moment.
The data types in the RAM model are integer and floating point (for storing real numbers). Although we typically do not concern ourselves with precision in this book, in some applications precision is crucial. We also assume a limit on the size of each word of data. For example, when working with inputs of size n, we typically assume that integers are represented by c lg n bits for some constant c >= 1. We require c >= 1 so that each word can hold the value of n, enabling us to index the individual input elements, and we restrict c to be a constant so that the word size does not grow arbitrarily. (If the word size could grow arbitrarily, we could store huge amounts of data in one word and operate on it all in constant time—clearly an unrealistic scenario.)
I like to think of the memory requirement as the number of integers required, not that the integers have to get larger. If we considered the size of the inters then traditional O(log n) memory algorithms (like the average case of quicksort) would be determined to take O((log n)^2) memory.
matches(n, m, string):
return matches((1{n}0{m})\*, string)
cannot.Just think about it -- the former is just a DFA, and so of course you can do it in constant space (provided your input stream is abstracted away, or you use a TM.
x++;
would be two examples.
Unknowingly you have allowed me to stumble onto an actual algorithm with O(1) storage pace, that is, one where there are n numbers, and you want to calculated the modulo-k sum. In this case, the algorithm scales logarithmically in the constant parameter k, but O(1) in n.
Furthermore, an array of size N is normally storing N variables (pointers) not N bits, so calculating storage required in bits relative to the input size (without a unit) is disingenuous.
To make it I needed a C++ version with iterators, which I though would be faster. But it is still about 20% slower than stable_sort for the default random input test. It probably also stays the same for other inputs.
"a few tweaks" is a bit of an understatement, at a high-level it's a hybrid of insertion and merge sort (it's an insertion sort below 64 elements, and it uses insertion sorts to create sorted sub-sections of 32~64 elements before applying the main merge sort)
- scans array to find merge-able runs (rather than use a "standard" size like more merge sorts); This makes it closer to O(n) for mostly-sorted arrays, a feature that is mostly associated with Bubble Sorts - but without giving up any of the good things about MergeSort
- identifies "reverse runs", and just reverses them - making mostly-reverse-sorted arrays closer to O(n), which no other general sort achieves.
It's still O(n log n) in the worst case - but it just works exceptionally well on real life datasets, which often have sorted or reversed sections.
TimSort as implemented in Python goes through the Python machinery of object comparison and object management in general. Make sure you do an apples<->apples comparison when benchmarking.
http://grepcode.com/file/repository.grepcode.com/java/root/j...
We've got Crossfilter (https://github.com/square/crossfilter/wiki/API-Reference); however, as more data moves client-side with storage APIs like IndexedDB, I see a need for "as efficient as possible"
This lead me to look up browser sort implementations; http://stackoverflow.com/questions/234683/javascript-array-s... - it seems Moz uses mergesort and Webkit may or may not do something silly for non contiguous arrays.
So, there could be a use for it. For most applications you're about fine as it is.
2. I'm interested in hearing about applications where you're loading millions of array elements in people's browsers.
I was going to be cranky and make rude comments but I can envision people wanting to play with their data without loading it in specialized toolsets/learn R/build a DSL in $lang_of_choice.
It purposefully pushes IDB way further than it should be taken in most cases.
UPDATE: I could not find the article I had initially in mind but I found this one [1] showing that even prominent implementations of simple algorithms like binary search or quicksort contain bugs more often than one expects and they may even remain unnoticed for decades.
So take this as a warning - if you implement this algorithm you will almost surely fail no matter how smart you are or how many people look at your implementation.
[1] http://googleresearch.blogspot.de/2006/06/extra-extra-read-a...
- take the two sorted arrays A & B (assume both are of size n) and make partitions of size log n in one of them, let's say A
- Now considering there are n/logn processors, assign each partition to a processor. On each partition take the last element (l) and do a binary search to find a cut point in the other array B such that all elements in B are <= l. Cut points of two such partitions in A correspond to a partition in B which can then be sequentially merged by the processor.
Span is O(log n); Work is O(n); so parallelism is O(n/logn) Detailed information here [1]
[0] https://github.com/BonzaiThePenguin/WikiSort/blob/master/Cha...
[1] http://electures.informatik.uni-freiburg.de/portal/download/...
I mean what sorts of big data sets are you sorting that much often ?
I mean unless you're a db software dev, and unless you're profiling it for each use case I wonder if you can really find something to optimize.
I just meant that's it's a niche. I honestly got no idea how db software are programmed but I doubt any dev can pretend to do better.
I guess that algorithm would interest people who recompile their db software, or who don't use those db software.
So here comes the question : what are the pro cons of using a db software ? Why would some devs still use plain files to store data ?
I'm not really an expert but it looks like this algorithm does sorting in a way that doesn't require as much extra memory as others..? I could be wrong about that, but the point is that this algorithm likely has some certain situations where it performs better than others.
[1]: http://www.cs.princeton.edu/~chazelle/pubs/selfimprove.pdf
The C code compares running time with a very standard mergesort.
The C++ code compares with std::stable_sort.
The Java code compares with a standard mergesort -- very similar to the code in the C version -- but has hard-to-predict JIT warmup effects.
The meaningful comparison would actually be to Heapsort, which is in-place, O(1) space, and NOT stable - though much, much, simpler.
ADDED:
Anyone who uses quicksort should read this gem from Doug McIlroy, which elicits an O(n^2) behaviour from most quicksort implementations: http://www.cs.dartmouth.edu/~doug/mdmspe.pdf -