summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1996-12-11 23:57:39 (GMT)
committerGuido van Rossum <guido@python.org>1996-12-11 23:57:39 (GMT)
commit3176bb1df2a81f2e0afb32eda47cf9c416fa7557 (patch)
tree8db98f965954a34e367b77cd74da1ffc8d33c0d9
parent042a207061b51de1570ff85cd7af61e585318589 (diff)
downloadcpython-3176bb1df2a81f2e0afb32eda47cf9c416fa7557.zip
cpython-3176bb1df2a81f2e0afb32eda47cf9c416fa7557.tar.gz
cpython-3176bb1df2a81f2e0afb32eda47cf9c416fa7557.tar.bz2
Some more tuning of quicksort: use pointers instead of indexing.
-rw-r--r--Objects/listobject.c114
1 files changed, 60 insertions, 54 deletions
diff --git a/Objects/listobject.c b/Objects/listobject.c
index 33ebe81..a985aa3 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -609,19 +609,20 @@ insertionsort(array, size, compare)
object *compare;/* Comparison function object, or NULL for default */
{
register object **a = array;
- register int i;
+ register object **end = array+size;
+ register object **p;
- for (i = 1; i < size; i++) {
- register object *key = a[i];
- register int j = i;
- while (--j >= 0) {
- register int k = docompare(a[j], key, compare);
+ for (p = a+1; p < end; p++) {
+ register object *key = *p;
+ register object **q = p;
+ while (--q >= a) {
+ register int k = docompare(*q, key, compare);
if (k == CMPERROR)
return -1;
if (k <= 0)
break;
- a[j+1] = a[j];
- a[j] = key; /* For consistency */
+ *(q+1) = *q;
+ *q = key; /* For consistency */
}
}
@@ -629,7 +630,9 @@ insertionsort(array, size, compare)
}
/* MINSIZE is the smallest array we care to partition; smaller arrays
- are sorted using a straight insertion sort (above). */
+ are sorted using a straight insertion sort (above). You may want
+ to play with this to tune it for your system. It must be at least
+ 2; more than 20 probably doesn't make sense. */
#define MINSIZE 10
/* STACKSIZE is the size of our work stack. A rough estimate is that
@@ -649,64 +652,66 @@ quicksort(array, size, compare)
int size; /* Number of elements to sort */
object *compare;/* Comparison function object, or NULL for default */
{
- register object **a, *tmp, *pivot;
- register int n, l, r, k;
- int top, i, j, n2;
- object **astack[STACKSIZE];
- int nstack[STACKSIZE];
+ register object *tmp, *pivot;
+ register object **lo, **hi, **l, **r;
+ int top, k, n, n2;
+ object **lostack[STACKSIZE];
+ object **histack[STACKSIZE];
/* Start out with the whole array on the work stack */
- astack[0] = array;
- nstack[0] = size;
+ lostack[0] = array;
+ histack[0] = array+size;
top = 1;
/* Repeat until the work stack is empty */
while (--top >= 0) {
- a = astack[top];
- n = nstack[top];
+ lo = lostack[top];
+ hi = histack[top];
/* If it's a small one, use straight insertion sort */
+ n = hi - lo;
if (n < MINSIZE) {
- if (insertionsort(a, n, compare) < 0)
+ if (insertionsort(lo, n, compare) < 0)
return -1;
continue;
}
- /* Choose median of a[0], a[n/2], a[n-1] as pivot */
- i = n>>1;
- j = n-1;
- k = docompare(a[0], a[i], compare);
+ /* Choose median of first, middle and last item as pivot */
+
+ l = lo + (n>>1); /* Middle */
+ r = hi - 1; /* Last */
+ k = docompare(*lo, *l, compare);
if (k == CMPERROR)
return -1;
if (k < 0)
- { tmp = a[0]; a[0] = a[i]; a[i] = tmp; }
- k = docompare(a[j], a[i], compare);
+ { tmp = *lo; *lo = *l; *l = tmp; }
+ k = docompare(*r, *l, compare);
if (k == CMPERROR)
return -1;
if (k < 0)
- { tmp = a[j]; a[j] = a[i]; a[i] = tmp; }
- k = docompare(a[j], a[0], compare);
+ { tmp = *r; *r = *l; *l = tmp; }
+ k = docompare(*r, *lo, compare);
if (k == CMPERROR)
return -1;
if (k < 0)
- { tmp = a[j]; a[j] = a[0]; a[0] = tmp; }
- pivot = a[0];
+ { tmp = *r; *r = *lo; *lo = tmp; }
+ pivot = *lo;
/* Partition the array */
- l = 0;
- r = n;
+ l = lo;
+ r = hi;
for (;;) {
/* Move left index to element > pivot */
- while (++l < n) {
- k = docompare(a[l], pivot, compare);
+ while (++l < hi) {
+ k = docompare(*l, pivot, compare);
if (k == CMPERROR)
return -1;
if (k > 0)
break;
}
/* Move right index to element < pivot */
- while (--r > 0) {
- k = docompare(a[r], pivot, compare);
+ while (--r > lo) {
+ k = docompare(*r, pivot, compare);
if (k == CMPERROR)
return -1;
if (k < 0)
@@ -716,40 +721,41 @@ quicksort(array, size, compare)
if (r < l)
break;
/* Swap elements and continue */
- { tmp = a[l]; a[l] = a[r]; a[r] = tmp; }
+ { tmp = *l; *l = *r; *r = tmp; }
}
/* Move the pivot into the middle */
- { tmp = a[0]; a[0] = a[r]; a[r] = tmp; }
+ { tmp = *lo; *lo = *r; *r = tmp; }
/* We have now reached the following conditions:
- 0 <= r < l <= n
- all x in a[0:r] are <= pivot
- all x in a[r:l] are == pivot
- all x in a[l:n] are >= pivot
- The partitions are a[0:r] and a[l:n]
+ lo <= r < l <= hi
+ all x in [lo,r) are <= pivot
+ all x in [r,l) are == pivot
+ all x in [l,hi) are >= pivot
+ The partitions are [lo,r) and [l,hi)
*/
/* Push biggest partition first */
- n2 = n - l;
- if (r > n2) {
+ n = r - lo;
+ n2 = hi - l;
+ if (n > n2) {
/* First one is bigger */
- if (r > 1) {
- astack[top] = a;
- nstack[top++] = r;
+ if (n > 1) {
+ lostack[top] = lo;
+ histack[top++] = r;
if (n2 > 1) {
- astack[top] = a+l;
- nstack[top++] = n2;
+ lostack[top] = l;
+ histack[top++] = hi;
}
}
} else {
/* Second one is bigger */
if (n2 > 1) {
- astack[top] = a+l;
- nstack[top++] = n2;
- if (r > 1) {
- astack[top] = a;
- nstack[top++] = r;
+ lostack[top] = l;
+ histack[top++] = hi;
+ if (n > 1) {
+ lostack[top] = lo;
+ histack[top++] = r;
}
}
}