Flashsort
Template:Short description Flashsort is a distribution sorting algorithm showing [[O notation|linear computational complexity Template:Mvar]] for uniformly distributed data sets and relatively little additional memory requirement. The original work was published in 1998 by Karl-Dietrich Neubert.[1]
Concept
Flashsort is an efficient in-place implementation of histogram sort, itself a type of bucket sort. It assigns each of the Template:Mvar input elements to one of Template:Mvar buckets, efficiently rearranges the input to place the buckets in the correct order, then sorts each bucket. The original algorithm sorts an input array Template:Mvar as follows:
- Using a first pass over the input or a priori knowledge, find the minimum and maximum sort keys.
- Linearly divide the range [Amin, Amax]Script error: No such module "Check for unknown parameters". into Template:Mvar buckets.
- Make one pass over the input, counting the number of elements Template:Mvar which fall into each bucket. (Neubert calls the buckets "classes" and the assignment of elements to their buckets "classification".)
- Convert the counts of elements in each bucket to a prefix sum, where Template:Mvar is the number of elements Template:Mvar in bucket Template:Mvar or less. (L0 = 0Script error: No such module "Check for unknown parameters". and Lm = nScript error: No such module "Check for unknown parameters"..)
- Rearrange the input so all elements of each bucket Template:Mvar are stored in positions Template:Mvar where Lb−1 < i ≤ LbScript error: No such module "Check for unknown parameters"..
- Sort each bucket using insertion sort.
Steps 1–3 and 6 are common to any bucket sort, and can be improved using techniques generic to bucket sorts. In particular, the goal is for the buckets to be of approximately equal size (n/mScript error: No such module "Check for unknown parameters". elements each),[1] with the ideal being division into Template:Mvar quantiles. While the basic algorithm is a linear interpolation sort, if the input distribution is known to be non-uniform, a non-linear division will more closely approximate this ideal. Likewise, the final sort can use any of a number of techniques, including a recursive flash sort.
What distinguishes flash sort is step 5: an efficient O(n)Script error: No such module "Check for unknown parameters". in-place algorithm for collecting the elements of each bucket together in the correct relative order using only Template:Mvar words of additional memory.
Memory efficient implementation
The Flashsort rearrangement phase operates in cycles. Elements start out "unclassified", then are moved to the correct bucket and considered "classified". The basic procedure is to choose an unclassified element, find its correct bucket, exchange it with an unclassified element there (which must exist, because we counted the size of each bucket ahead of time), mark it as classified, and then repeat with the just-exchanged unclassified element. Eventually, the element is exchanged with itself and the cycle ends.
The details are easy to understand using two (word-sized) variables per bucket. The clever part is the elimination of one of those variables, allowing twice as many buckets to be used and therefore half as much time spent on the final O(n2)Script error: No such module "Check for unknown parameters". sorting.
To understand it with two variables per bucket, assume there are two arrays of Template:Mvar additional words: Template:Mvar is the (fixed) upper limit of bucket Template:Mvar (and K0 = 0Script error: No such module "Check for unknown parameters".), while Template:Mvar is a (movable) index into bucket Template:Mvar, so Kb−1 ≤ Lb ≤ KbScript error: No such module "Check for unknown parameters"..
We maintain the loop invariant that each bucket is divided by Template:Mvar into an unclassified prefix (Template:Mvar for Kb−1 < i ≤ LbScript error: No such module "Check for unknown parameters". have yet to be moved to their target buckets) and a classified suffix (Template:Mvar for Lb < i ≤ KbScript error: No such module "Check for unknown parameters". are all in the correct bucket and will not be moved again). Initially Lb = KbScript error: No such module "Check for unknown parameters". and all elements are unclassified. As sorting proceeds, the Template:Mvar are decremented until Lb = Kb−1Script error: No such module "Check for unknown parameters". for all Template:Mvar and all elements are classified into the correct bucket.
Each round begins by finding the first incompletely classified bucket Template:Mvar (which has Kc−1 < LcScript error: No such module "Check for unknown parameters".) and taking the first unclassified element in that bucket Template:Mvar where i = Kc−1 + 1Script error: No such module "Check for unknown parameters".. (Neubert calls this the "cycle leader".) Copy Template:Mvar to a temporary variable Template:Mvar and repeat:
- Compute the bucket Template:Mvar to which Template:Mvar belongs.
- Let j = LbScript error: No such module "Check for unknown parameters". be the location where Template:Mvar will be stored.
- Exchange Template:Mvar with Template:Mvar, i.e. store Template:Mvar in Template:Mvar while fetching the previous value Template:Mvar thereby displaced.
- Decrement Template:Mvar to reflect the fact that Template:Mvar is now correctly classified.
- If j ≠ iScript error: No such module "Check for unknown parameters"., restart this loop with the new Template:Mvar.
- If j = iScript error: No such module "Check for unknown parameters"., this round is over and find a new first unclassified element Template:Mvar.
- When there are no more unclassified elements, the distribution into buckets is complete.
When implemented with two variables per bucket in this way, the choice of each round's starting point Template:Mvar is in fact arbitrary; any unclassified element may be used as a cycle leader. The only requirement is that the cycle leaders can be found efficiently.
Although the preceding description uses Template:Mvar to find the cycle leaders, it is in fact possible to do without it, allowing the entire Template:Mvar-word array to be eliminated. (After the distribution is complete, the bucket boundaries can be found in Template:Mvar.)
Suppose that we have classified all elements up to i−1Script error: No such module "Check for unknown parameters"., and are considering Template:Mvar as a potential new cycle leader. It is easy to compute its target bucket Template:Mvar. By the loop invariant, it is classified if Lb < i ≤ KbScript error: No such module "Check for unknown parameters"., and unclassified if Template:Mvar is outside that range. The first inequality is easy to test, but the second appears to require the value Template:Mvar.
It turns out that the induction hypothesis that all elements up to i−1Script error: No such module "Check for unknown parameters". are classified implies that i ≤ KbScript error: No such module "Check for unknown parameters"., so it is not necessary to test the second inequality.
Consider the bucket Template:Mvar which position Template:Mvar falls into. That is, Kc−1 < i ≤ KcScript error: No such module "Check for unknown parameters".. By the induction hypothesis, all elements below Template:Mvar, which includes all buckets up to Kc−1 < iScript error: No such module "Check for unknown parameters"., are completely classified. I.e. no elements which belong in those buckets remain in the rest of the array. Therefore, it is not possible that b < cScript error: No such module "Check for unknown parameters"..
The only remaining case is b ≥ cScript error: No such module "Check for unknown parameters"., which implies Kb ≥ Kc ≥ iScript error: No such module "Check for unknown parameters"., Q.E.D.
Incorporating this, the flashsort distribution algorithm begins with Template:Mvar as described above and i = 1Script error: No such module "Check for unknown parameters".. Then proceed:[1][2]
- If i > nScript error: No such module "Check for unknown parameters"., the distribution is complete.
- Given Template:Mvar, compute the bucket Template:Mvar to which it belongs.
- If i ≤ LbScript error: No such module "Check for unknown parameters"., then Template:Mvar is unclassified. Copy it a temporary variable Template:Mvar and:
- Let j = LbScript error: No such module "Check for unknown parameters". be the location where Template:Mvar will be stored.
- Exchange Template:Mvar with Template:Mvar, i.e. store Template:Mvar in Template:Mvar while fetching the previous value Template:Mvar thereby displaced.
- Decrement Template:Mvar to reflect the fact that Template:Mvar is now correctly classified.
- If j ≠ iScript error: No such module "Check for unknown parameters"., compute the bucket Template:Mvar to which Template:Mvar belongs and restart this (inner) loop with the new Template:Mvar.
- Template:Mvar is now correctly classified. Increment Template:Mvar and restart the (outer) loop.
While saving memory, Flashsort has the disadvantage that it recomputes the bucket for many already-classified elements. This is already done twice per element (once during the bucket-counting phase and a second time when moving each element), but searching for the first unclassified element requires a third computation for most elements. This could be expensive if buckets are assigned using a more complex formula than simple linear interpolation. A variant reduces the number of computations from almost 3nScript error: No such module "Check for unknown parameters". to at most 2n + m − 1Script error: No such module "Check for unknown parameters". by taking the last unclassified element in an unfinished bucket as cycle leader:
- Maintain a variable Template:Mvar identifying the first incompletely-classified bucket. Let c = 1Script error: No such module "Check for unknown parameters". to begin with, and when Template:Mvar, the distribution is complete.
- Let i = LcScript error: No such module "Check for unknown parameters".. If i = Lc−1Script error: No such module "Check for unknown parameters"., increment Template:Mvar and restart this loop. (L0 = 0Script error: No such module "Check for unknown parameters"..)
- Compute the bucket Template:Mvar to which Template:Mvar belongs.
- If b < cScript error: No such module "Check for unknown parameters"., then Lc = Kc−1Script error: No such module "Check for unknown parameters". and we are done with bucket Template:Mvar. Increment Template:Mvar and restart this loop.
- If b = cScript error: No such module "Check for unknown parameters"., the classification is trivial. Decrement Template:Mvar and restart this loop.
- If b > cScript error: No such module "Check for unknown parameters"., then Template:Mvar is unclassified. Perform the same classification loop as the previous case, then restart this loop.
Most elements have their buckets computed only twice, except for the final element in each bucket, which is used to detect the completion of the following bucket. A small further reduction can be achieved by maintaining a count of unclassified elements and stopping when it reaches zero.
Performance
The only extra memory requirements are the auxiliary vector Template:Mvar for storing bucket bounds and the constant number of other variables used. Further, each element is moved (via a temporary buffer, so two move operations) only once. However, this memory efficiency comes with the disadvantage that the array is accessed randomly, so cannot take advantage of a data cache smaller than the whole array.
As with all bucket sorts, performance depends critically on the balance of the buckets. In the ideal case of a balanced data set, each bucket will be approximately the same size. If the number Template:Mvar of buckets is linear in the input size Template:Mvar, each bucket has a constant size, so sorting a single bucket with an O(n2)Script error: No such module "Check for unknown parameters". algorithm like insertion sort has complexity O(12) = O(1)Script error: No such module "Check for unknown parameters".. The running time of the final insertion sorts is therefore m ⋅ O(1) = O(m) = O(n)Script error: No such module "Check for unknown parameters"..
Choosing a value for Template:Mvar, the number of buckets, trades off time spent classifying elements (high Template:Mvar) and time spent in the final insertion sort step (low Template:Mvar). For example, if Template:Mvar is chosen proportional to
- REDIRECT Template:Radic
Template:Rcat shellScript error: No such module "Check for unknown parameters"., then the running time of the final insertion sorts is therefore m ⋅ O(
- REDIRECT Template:Radic
Template:Rcat shell2Script error: No such module "Check for unknown parameters".) = O(n3/2)Script error: No such module "Check for unknown parameters"..
In the worst-case scenarios where almost all the elements are in a few buckets, the complexity of the algorithm is limited by the performance of the final bucket-sorting method, so degrades to O(n2)Script error: No such module "Check for unknown parameters".. Variations of the algorithm improve worst-case performance by using better-performing sorts such as quicksort or recursive flashsort on buckets which exceed a certain size limit.[2][3]
For m = 0.1 nScript error: No such module "Check for unknown parameters". with uniformly distributed random data, flashsort is faster than heapsort for all Template:Mvar and faster than quicksort for n > 80Script error: No such module "Check for unknown parameters".. It becomes about twice as fast as quicksort at n = 10000Script error: No such module "Check for unknown parameters"..[1] Note that these measurements were taken in the late 1990s, when memory hierarchies were much less dependent on cacheing.
Due to the in situ permutation that flashsort performs in its classification process, flashsort is not stable. If stability is required, it is possible to use a second array so elements can be classified sequentially. However, in this case, the algorithm will require O(n)Script error: No such module "Check for unknown parameters". additional memory.
See also
- Interpolation search, using the distribution of items for searching rather than sorting
References
<templatestyles src="Reflist/styles.css" />
Script error: No such module "Check for unknown parameters".
External links
- Implementations of Randomized Sorting on Large Parallel Machines (1992)
- Implementation of Parallel Algorithms (1992)
- Visualization of Flashsort Template:Webarchive
Script error: No such module "Navbox".