Commit 2fdfb0e4 authored by Guido van Rossum's avatar Guido van Rossum

Modified quicksort by Raymund Galvin, after studying the GNU libg++

quicksort.  This should be much faster if there are lots of
duplicates, and otherwise at least as good.
parent 810f8bf2
...@@ -683,8 +683,10 @@ quicksort(array, size, compare) ...@@ -683,8 +683,10 @@ quicksort(array, size, compare)
/* If it's a small one, use straight insertion sort */ /* If it's a small one, use straight insertion sort */
n = hi - lo; n = hi - lo;
if (n < MINSIZE) { if (n < MINSIZE) {
if (insertionsort(lo, n, compare) < 0) /*
return -1; * skip it. The insertion sort at the end will
* catch these
*/
continue; continue;
} }
...@@ -692,52 +694,64 @@ quicksort(array, size, compare) ...@@ -692,52 +694,64 @@ quicksort(array, size, compare)
l = lo + (n>>1); /* Middle */ l = lo + (n>>1); /* Middle */
r = hi - 1; /* Last */ r = hi - 1; /* Last */
k = docompare(*lo, *l, compare);
k = docompare(*l, *lo, compare);
if (k == CMPERROR) if (k == CMPERROR)
return -1; return -1;
if (k < 0) if (k < 0)
{ tmp = *lo; *lo = *l; *l = tmp; } { tmp = *lo; *lo = *l; *l = tmp; }
k = docompare(*r, *l, compare); k = docompare(*r, *l, compare);
if (k == CMPERROR) if (k == CMPERROR)
return -1; return -1;
if (k < 0) if (k < 0)
{ tmp = *r; *r = *l; *l = tmp; } { tmp = *r; *r = *l; *l = tmp; }
k = docompare(*r, *lo, compare);
k = docompare(*l, *lo, compare);
if (k == CMPERROR) if (k == CMPERROR)
return -1; return -1;
if (k < 0) if (k < 0)
{ tmp = *r; *r = *lo; *lo = tmp; } { tmp = *l; *l = *lo; *lo = tmp; }
pivot = *lo; pivot = *l;
/* Partition the array */ /* Partition the array */
l = lo; l = lo+1;
r = hi; r = hi-2;
for (;;) { for (;;) {
/* Move left index to element > pivot */ /* Move left index to element > pivot */
while (++l < hi) { for (;;) {
k = docompare(*l, pivot, compare); k = docompare(*l, pivot, compare);
if (k == CMPERROR) if (k == CMPERROR)
return -1; return -1;
if (k > 0) if (k >= 0)
break; break;
l++;
} }
/* Move right index to element < pivot */ /* Move right index to element < pivot */
while (--r > lo) { for (;;) {
k = docompare(*r, pivot, compare); k = docompare(pivot, *r, compare);
if (k == CMPERROR) if (k == CMPERROR)
return -1; return -1;
if (k < 0) if (k >= 0)
break; break;
r--;
} }
/* If they met, we're through */ /* If they met, we're through */
if (r < l) if (l < r) {
break;
/* Swap elements and continue */ /* Swap elements and continue */
{ tmp = *l; *l = *r; *r = tmp; } tmp = *l; *l = *r; *r = tmp;
l++; r--;
}
else if (l == r) {
l++; r--;
break;
}
if (l > r)
break;
} }
/* Move the pivot into the middle */
{ tmp = *lo; *lo = *r; *r = tmp; }
/* We have now reached the following conditions: /* We have now reached the following conditions:
lo <= r < l <= hi lo <= r < l <= hi
...@@ -752,20 +766,20 @@ quicksort(array, size, compare) ...@@ -752,20 +766,20 @@ quicksort(array, size, compare)
n2 = hi - l; n2 = hi - l;
if (n > n2) { if (n > n2) {
/* First one is bigger */ /* First one is bigger */
if (n > 1) { if (n > MINSIZE) {
lostack[top] = lo; lostack[top] = lo;
histack[top++] = r; histack[top++] = r;
if (n2 > 1) { if (n2 > MINSIZE) {
lostack[top] = l; lostack[top] = l;
histack[top++] = hi; histack[top++] = hi;
} }
} }
} else { } else {
/* Second one is bigger */ /* Second one is bigger */
if (n2 > 1) { if (n2 > MINSIZE) {
lostack[top] = l; lostack[top] = l;
histack[top++] = hi; histack[top++] = hi;
if (n > 1) { if (n > MINSIZE) {
lostack[top] = lo; lostack[top] = lo;
histack[top++] = r; histack[top++] = r;
} }
...@@ -775,6 +789,17 @@ quicksort(array, size, compare) ...@@ -775,6 +789,17 @@ quicksort(array, size, compare)
/* Should assert top < STACKSIZE-1 */ /* Should assert top < STACKSIZE-1 */
} }
/*
* Ouch - even if I screwed up the quicksort above, the
* insertionsort below will cover up the problem - just a
* performance hit would be noticable.
*/
/* insertionsort is pretty fast on the partially sorted list */
if (insertionsort(array, size, compare) < 0)
return -1;
/* Succes */ /* Succes */
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment