]> git.kaiwu.me - klib.git/commitdiff
improved my implementation of radix sort
authorHeng Li <lh3@me.com>
Fri, 8 Jun 2012 23:00:25 +0000 (19:00 -0400)
committerHeng Li <lh3@me.com>
Fri, 8 Jun 2012 23:00:25 +0000 (19:00 -0400)
test/ksort_test.cc

index e4c937b17b8edf0f60c4c2f1b78270c06b44fe2d..49b08cb08bd94fc77004f86183a11ea9f2fc7375 100644 (file)
@@ -594,41 +594,41 @@ typedef struct {
        rstype_t *b, *e;
 } rsbucket_t;
 
-void rs_classify(rstype_t *beg, rstype_t *end, int n_bits, int s, rsbucket_t *b)
+void rs_sort(rstype_t *beg, rstype_t *end, int n_bits, int s)
 {
-       rstype_t *i, tmp;
-       int m = (1<<n_bits) - 1;
-       rsbucket_t *k, *l, *be;
+       rstype_t *i;
+       int size = 1<<n_bits, m = size - 1;
+       rsbucket_t *k, b[size], *be = b + size;
 
-       be = b + (1<<n_bits);
        for (k = b; k != be; ++k) k->b = k->e = beg;
        for (i = beg; i != end; ++i) ++b[rskey(*i)>>s&m].e;
-       if (b[0].e == end) return; // no need to sort
-       for (k = b + 1; k != be; ++k)
-               k->e += (k-1)->e - beg, k->b = (k-1)->e;
-       for (k = b; k != be;) {
-               if (k->b == k->e) { ++k; continue; }
-               l = b + (rskey(*k->b)>>s&m);
-               if (k == l) { ++k->b; continue; }
-               tmp = *l->b; *l->b++ = *k->b; *k->b = tmp;
+       if (b[0].e != end) {
+               for (k = b + 1; k != be; ++k)
+                       k->e += (k-1)->e - beg, k->b = (k-1)->e;
+               for (k = b; k != be;) {
+                       rstype_t t[2];
+                       rsbucket_t *l;
+                       int curr = 0;
+                       if (k->b == k->e) { ++k; continue; }
+                       l = b + (rskey(*k->b)>>s&m);
+                       if (k == l) { ++k->b; continue; }
+                       t[curr] = *k->b;
+                       do {
+                               t[!curr] = *l->b; *l->b++ = t[curr];
+                               curr = !curr;
+                               l = b + (rskey(t[curr])>>s&m);
+                       } while (l != k);
+                       *k->b++ = t[curr];
+               }
+               for (b->b = beg, k = b + 1; k != be; ++k) k->b = (k-1)->e;
        }
-       for (k = b + 1; k != be; ++k) k->b = (k-1)->e;
-       b->b = beg;
-}
-
-void rs_sort(rstype_t *beg, rstype_t *end, int n_bits, int s)
-{
-       if (end - beg > RS_MIN_SIZE) {
-               rsbucket_t *b;
-               int i;
-               b = (rsbucket_t*)alloca(sizeof(rsbucket_t) * (1<<n_bits));
-               rs_classify(beg, end, n_bits, s, b);
-               if (s) {
-                       s = s > n_bits? s - n_bits : 0;
-                       for (i = 0; i != 1<<n_bits; ++i)
-                               if (b[i].e > b[i].b + 1) rs_sort(b[i].b, b[i].e, n_bits, s);
+       if (s) {
+               s = s > n_bits? s - n_bits : 0;
+               for (k = b; k != be; ++k) {
+                       if (k->e - k->b > RS_MIN_SIZE) rs_sort(k->b, k->e, n_bits, s);
+                       else if (k->e - k->b > 1) rs_insertsort(k->b, k->e);
                }
-       } else if (end - beg > 1) rs_insertsort(beg, end);
+       }
 }
 
 /*************************************************