From: Martin Knoblauch Revuelta on
I am very interested in the sorting algorithm Combsort. It is
basically a modified Bubblesort that exploits the concept of
exchanging far elements. Quicksort and Shellsort are based on the same
idea.

There is a very good descrition of Combsort in the Wikipedia (http://
en.wikipedia.org/wiki/Comb_sort). In short: As Bubblesort, Combsort
iterates several times along the data, comparing pairs of elements and
swapping them if they are not in order with respect to each other. The
difference is that Bubblesort always compares/swaps contiguous
elements, while Combsort compares/swaps elements separated by a gap.
The initial gap is the size of the array, and it is divided by a
shrink factor every time the end is reached. Finally, several passes
(hopefully just one) with gap 1 end the job.

Stephen Lacey and Richard Box ("A Fast, Easy Sort", Byte, April 1991)
found experimentally an "ideal" shrink factor of 1.3. With a patch
that they called Combsort11, they claimed to "kill all miniturtles".
Though, with today's computers, it is easy to find sequences that
require several passes with a final gap of 1. The number of passes
required is low, but it seems to be proportional to the size of the
array. This makes Combsort suspicious of O(n^2) time (worst case).

NOTE: In May 1997, D. J. Bernstein wrote in comp.theory:
> Background: Knuth, in exercise 5.2.1-40, described
> a variant of Shellsort where you don't back up when
> the step size exceeds 1. This was reinvented many
> years later and presented as ``Combsort,'' with
> massive hype, in the April 1991 BYTE.

The Wikipedia also mentions a theoretical shrink factor 1/(1-exp(-
phi)) = 1.247330950103979 that guarantees that only one pass of gap 1
is required. That is, it guarantees O(n log n) worst case time.

The question is: Can anybody prove it?

The sources of this magical number have been evaporated. Does anybody
know where this came from?

I tried myself the shrink factor 1.247... and I didn't find any
"killer" sequence requiring more than one pass with gap 1.

Other sources (evaporated too) mention larger values for the shrink
factor. I tried to find, by binary search, the exact boundary. My
results suggest that a shrink factor strictly lesser than 9/7 is safe.

Note that I can only prove that 9/7 (and all other greater values I
tried) are _not_ safe. Indeed, 1.279604943109628 is mentioned in the
talk page of the Wikipedia... making me suspect that somebody found a
sequence that would kill <9/7. By the way, does anybody know such
sequence?

Here is the code written in 'non-cryptic' C:
--------------------------------------------------------
void combsort_9_7 (unsigned int A[], unsigned int len)
{
unsigned int i, j, tmp, gap;

gap = len;
// No "sorted" flag! The number of
while (gap>1) // iterations only depends on the size
{
if (gap<10) // Below 10, descend one
gap = gap - 1; // by one until zero
else
gap = (gap*7)/9 + 1; // Integer division!!
// +1: ensure shrink factor
i = 0; // strictly < 9/7
j = gap;

while (j<len) // Make a pass with current gap
{
if (A[i]>A[j]) // If not sorted ...
{
tmp = A[i];
A[i] = A[j]; // ... swap!
A[j] = tmp;
}

i = i + 1; // Advance
j = j + 1;
}
}
}
--------------------------------------------------------

And here is the 'true' C version (probably generates the same
assembler output):
--------------------------------------------------------
void combsort_9_7 (unsigned A[], unsigned len)
{
unsigned i, j, tmp, gap;

gap = len;

while (gap>1)
{
gap = gap<10 ? gap-1 : gap*7/9+1;

for (i=0, j=gap; j<len; i++, j++)
if (A[i]>A[j])
{
tmp = A[i];
A[i] = A[j];
A[j] = tmp;
}
}
}
--------------------------------------------------------

The reason why I am so interested in Combsort is the combination of:
a) good worst-case behaviour (only if a proof is found...)
b) simplicity
c) predictability (memory addresses are always accessed in the same
fashion)

This eases the calculation of the worst case execution time, making
Combsort a good candidate for Real Time applications.

By the way, here are some timings in seconds, for sequences of 88145
elements with no repeated values:

Combsort 0.0187 (see code above)
Heapsort 0.0143 (optimized chain-swaps)
Quicksort 0.0134 (pivot chosen at random,
explicit stack and careful tail recursion
avoid function calls and stack overflow,
switch to selection sort when size<=8)

With 429993 elements:

Combsort 0.0926 seconds
Heapsort 0.0794 "
Quicksort 0.0676 "

Hardware used: PC with Intel Core 2 T7200 @ 2GHz, 2GB of RAM

Thanks in advance,
Martin
 | 
Pages: 1
Prev: DPA-128 block ciphering questions
Next: jobs