mirror of
https://github.com/python/cpython.git
synced 2025-09-28 19:25:27 +00:00
Some more tuning of quicksort: use pointers instead of indexing.
This commit is contained in:
parent
042a207061
commit
3176bb1df2
1 changed files with 60 additions and 54 deletions
|
@ -609,19 +609,20 @@ insertionsort(array, size, compare)
|
||||||
object *compare;/* Comparison function object, or NULL for default */
|
object *compare;/* Comparison function object, or NULL for default */
|
||||||
{
|
{
|
||||||
register object **a = array;
|
register object **a = array;
|
||||||
register int i;
|
register object **end = array+size;
|
||||||
|
register object **p;
|
||||||
|
|
||||||
for (i = 1; i < size; i++) {
|
for (p = a+1; p < end; p++) {
|
||||||
register object *key = a[i];
|
register object *key = *p;
|
||||||
register int j = i;
|
register object **q = p;
|
||||||
while (--j >= 0) {
|
while (--q >= a) {
|
||||||
register int k = docompare(a[j], key, compare);
|
register int k = docompare(*q, key, compare);
|
||||||
if (k == CMPERROR)
|
if (k == CMPERROR)
|
||||||
return -1;
|
return -1;
|
||||||
if (k <= 0)
|
if (k <= 0)
|
||||||
break;
|
break;
|
||||||
a[j+1] = a[j];
|
*(q+1) = *q;
|
||||||
a[j] = key; /* For consistency */
|
*q = key; /* For consistency */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -629,7 +630,9 @@ insertionsort(array, size, compare)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* MINSIZE is the smallest array we care to partition; smaller arrays
|
/* 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
|
#define MINSIZE 10
|
||||||
|
|
||||||
/* STACKSIZE is the size of our work stack. A rough estimate is that
|
/* 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 */
|
int size; /* Number of elements to sort */
|
||||||
object *compare;/* Comparison function object, or NULL for default */
|
object *compare;/* Comparison function object, or NULL for default */
|
||||||
{
|
{
|
||||||
register object **a, *tmp, *pivot;
|
register object *tmp, *pivot;
|
||||||
register int n, l, r, k;
|
register object **lo, **hi, **l, **r;
|
||||||
int top, i, j, n2;
|
int top, k, n, n2;
|
||||||
object **astack[STACKSIZE];
|
object **lostack[STACKSIZE];
|
||||||
int nstack[STACKSIZE];
|
object **histack[STACKSIZE];
|
||||||
|
|
||||||
/* Start out with the whole array on the work stack */
|
/* Start out with the whole array on the work stack */
|
||||||
astack[0] = array;
|
lostack[0] = array;
|
||||||
nstack[0] = size;
|
histack[0] = array+size;
|
||||||
top = 1;
|
top = 1;
|
||||||
|
|
||||||
/* Repeat until the work stack is empty */
|
/* Repeat until the work stack is empty */
|
||||||
while (--top >= 0) {
|
while (--top >= 0) {
|
||||||
a = astack[top];
|
lo = lostack[top];
|
||||||
n = nstack[top];
|
hi = histack[top];
|
||||||
|
|
||||||
/* If it's a small one, use straight insertion sort */
|
/* If it's a small one, use straight insertion sort */
|
||||||
|
n = hi - lo;
|
||||||
if (n < MINSIZE) {
|
if (n < MINSIZE) {
|
||||||
if (insertionsort(a, n, compare) < 0)
|
if (insertionsort(lo, n, compare) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Choose median of a[0], a[n/2], a[n-1] as pivot */
|
/* Choose median of first, middle and last item as pivot */
|
||||||
i = n>>1;
|
|
||||||
j = n-1;
|
l = lo + (n>>1); /* Middle */
|
||||||
k = docompare(a[0], a[i], compare);
|
r = hi - 1; /* Last */
|
||||||
|
k = docompare(*lo, *l, compare);
|
||||||
if (k == CMPERROR)
|
if (k == CMPERROR)
|
||||||
return -1;
|
return -1;
|
||||||
if (k < 0)
|
if (k < 0)
|
||||||
{ tmp = a[0]; a[0] = a[i]; a[i] = tmp; }
|
{ tmp = *lo; *lo = *l; *l = tmp; }
|
||||||
k = docompare(a[j], a[i], compare);
|
k = docompare(*r, *l, compare);
|
||||||
if (k == CMPERROR)
|
if (k == CMPERROR)
|
||||||
return -1;
|
return -1;
|
||||||
if (k < 0)
|
if (k < 0)
|
||||||
{ tmp = a[j]; a[j] = a[i]; a[i] = tmp; }
|
{ tmp = *r; *r = *l; *l = tmp; }
|
||||||
k = docompare(a[j], a[0], compare);
|
k = docompare(*r, *lo, compare);
|
||||||
if (k == CMPERROR)
|
if (k == CMPERROR)
|
||||||
return -1;
|
return -1;
|
||||||
if (k < 0)
|
if (k < 0)
|
||||||
{ tmp = a[j]; a[j] = a[0]; a[0] = tmp; }
|
{ tmp = *r; *r = *lo; *lo = tmp; }
|
||||||
pivot = a[0];
|
pivot = *lo;
|
||||||
|
|
||||||
/* Partition the array */
|
/* Partition the array */
|
||||||
l = 0;
|
l = lo;
|
||||||
r = n;
|
r = hi;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/* Move left index to element > pivot */
|
/* Move left index to element > pivot */
|
||||||
while (++l < n) {
|
while (++l < hi) {
|
||||||
k = docompare(a[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;
|
||||||
}
|
}
|
||||||
/* Move right index to element < pivot */
|
/* Move right index to element < pivot */
|
||||||
while (--r > 0) {
|
while (--r > lo) {
|
||||||
k = docompare(a[r], pivot, compare);
|
k = docompare(*r, pivot, compare);
|
||||||
if (k == CMPERROR)
|
if (k == CMPERROR)
|
||||||
return -1;
|
return -1;
|
||||||
if (k < 0)
|
if (k < 0)
|
||||||
|
@ -716,40 +721,41 @@ quicksort(array, size, compare)
|
||||||
if (r < l)
|
if (r < l)
|
||||||
break;
|
break;
|
||||||
/* Swap elements and continue */
|
/* 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 */
|
/* 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:
|
/* We have now reached the following conditions:
|
||||||
0 <= r < l <= n
|
lo <= r < l <= hi
|
||||||
all x in a[0:r] are <= pivot
|
all x in [lo,r) are <= pivot
|
||||||
all x in a[r:l] are == pivot
|
all x in [r,l) are == pivot
|
||||||
all x in a[l:n] are >= pivot
|
all x in [l,hi) are >= pivot
|
||||||
The partitions are a[0:r] and a[l:n]
|
The partitions are [lo,r) and [l,hi)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Push biggest partition first */
|
/* Push biggest partition first */
|
||||||
n2 = n - l;
|
n = r - lo;
|
||||||
if (r > n2) {
|
n2 = hi - l;
|
||||||
|
if (n > n2) {
|
||||||
/* First one is bigger */
|
/* First one is bigger */
|
||||||
if (r > 1) {
|
if (n > 1) {
|
||||||
astack[top] = a;
|
lostack[top] = lo;
|
||||||
nstack[top++] = r;
|
histack[top++] = r;
|
||||||
if (n2 > 1) {
|
if (n2 > 1) {
|
||||||
astack[top] = a+l;
|
lostack[top] = l;
|
||||||
nstack[top++] = n2;
|
histack[top++] = hi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Second one is bigger */
|
/* Second one is bigger */
|
||||||
if (n2 > 1) {
|
if (n2 > 1) {
|
||||||
astack[top] = a+l;
|
lostack[top] = l;
|
||||||
nstack[top++] = n2;
|
histack[top++] = hi;
|
||||||
if (r > 1) {
|
if (n > 1) {
|
||||||
astack[top] = a;
|
lostack[top] = lo;
|
||||||
nstack[top++] = r;
|
histack[top++] = r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue