From ffebcd5fdbf870c998a80bd5725c41bb2bc84442 Mon Sep 17 00:00:00 2001 From: Jian Date: Thu, 3 Oct 2019 17:04:48 +1000 Subject: [PATCH] Added multikey quicksort --- sorting/multikey_quicksort.c | 407 +++++++++++++++++++++++++++++++++++ 1 file changed, 407 insertions(+) create mode 100644 sorting/multikey_quicksort.c diff --git a/sorting/multikey_quicksort.c b/sorting/multikey_quicksort.c new file mode 100644 index 00000000..7077aa53 --- /dev/null +++ b/sorting/multikey_quicksort.c @@ -0,0 +1,407 @@ +/* demo.c -- Implementations of multikey quicksort and ternary search trees + Usage + demo Run basic timings on /usr/dict/words + demo Run basic timings on + demo trysearch Interactive pm and nn search on + demo nncost Run near neigbhor expers on + demo pmcost Interactive partial match expers on + */ + +#include +#include +#include +#include + +// MULTIKEY QUICKSORT + +#ifndef min +#define min(a, b) ((a) <= (b) ? (a) : (b)) +#endif + +#define swap(a, b) \ + { \ + char *t = x[a]; \ + x[a] = x[b]; \ + x[b] = t; \ + } +#define i2c(i) x[i][depth] + +void vecswap(int i, int j, int n, char *x[]) +{ + while (n-- > 0) + { + swap(i, j); + i++; + j++; + } +} + +void ssort1(char *x[], int n, int depth) +{ + int a, b, c, d, r, v; + if (n <= 1) + return; + a = rand() % n; + swap(0, a); + v = i2c(0); + a = b = 1; + c = d = n - 1; + for (;;) + { + while (b <= c && (r = i2c(b) - v) <= 0) + { + if (r == 0) + { + swap(a, b); + a++; + } + b++; + } + while (b <= c && (r = i2c(c) - v) >= 0) + { + if (r == 0) + { + swap(c, d); + d--; + } + c--; + } + if (b > c) + break; + swap(b, c); + b++; + c--; + } + r = min(a, b - a); + vecswap(0, b - r, r, x); + r = min(d - c, n - d - 1); + vecswap(b, n - r, r, x); + r = b - a; + ssort1(x, r, depth); + if (i2c(r) != 0) + ssort1(x + r, a + n - d - 1, depth + 1); + r = d - c; + ssort1(x + n - r, r, depth); +} + +void ssort1main(char *x[], int n) +{ + ssort1(x, n, 0); +} + +// ssort2 -- Faster Version of Multikey Quicksort + +void vecswap2(char **a, char **b, int n) +{ + while (n-- > 0) + { + char *t = *a; + *a++ = *b; + *b++ = t; + } +} + +#define swap2(a, b) \ + { \ + t = *(a); \ + *(a) = *(b); \ + *(b) = t; \ + } +#define ptr2char(i) (*(*(i) + depth)) + +char **med3func(char **a, char **b, char **c, int depth) +{ + int va, vb, vc; + if ((va = ptr2char(a)) == (vb = ptr2char(b))) + return a; + if ((vc = ptr2char(c)) == va || vc == vb) + return c; + return va < vb ? (vb < vc ? b : (va < vc ? c : a)) + : (vb > vc ? b : (va < vc ? a : c)); +} +#define med3(a, b, c) med3func(a, b, c, depth) + +void inssort(char **a, int n, int d) +{ + char **pi, **pj, *s, *t; + for (pi = a + 1; --n > 0; pi++) + for (pj = pi; pj > a; pj--) + { + // Inline strcmp: break if *(pj-1) <= *pj + for (s = *(pj - 1) + d, t = *pj + d; *s == *t && *s != 0; s++, t++) + ; + if (*s <= *t) + break; + swap2(pj, pj - 1); + } +} + +void ssort2(char **a, int n, int depth) +{ + int d, r, partval; + char **pa, **pb, **pc, **pd, **pl, **pm, **pn, *t; + if (n < 10) + { + inssort(a, n, depth); + return; + } + pl = a; + pm = a + (n / 2); + pn = a + (n - 1); + if (n > 30) + { // On big arrays, pseudomedian of 9 + d = (n / 8); + pl = med3(pl, pl + d, pl + 2 * d); + pm = med3(pm - d, pm, pm + d); + pn = med3(pn - 2 * d, pn - d, pn); + } + pm = med3(pl, pm, pn); + swap2(a, pm); + partval = ptr2char(a); + pa = pb = a + 1; + pc = pd = a + n - 1; + for (;;) + { + while (pb <= pc && (r = ptr2char(pb) - partval) <= 0) + { + if (r == 0) + { + swap2(pa, pb); + pa++; + } + pb++; + } + while (pb <= pc && (r = ptr2char(pc) - partval) >= 0) + { + if (r == 0) + { + swap2(pc, pd); + pd--; + } + pc--; + } + if (pb > pc) + break; + swap2(pb, pc); + pb++; + pc--; + } + pn = a + n; + r = min(pa - a, pb - pa); + vecswap2(a, pb - r, r); + r = min(pd - pc, pn - pd - 1); + vecswap2(pb, pn - r, r); + if ((r = pb - pa) > 1) + ssort2(a, r, depth); + if (ptr2char(a + r) != 0) + ssort2(a + r, pa - a + pn - pd - 1, depth + 1); + if ((r = pd - pc) > 1) + ssort2(a + n - r, r, depth); +} + +void ssort2main(char **a, int n) { ssort2(a, n, 0); } + +// TERNARY SEARCH TREE ALGS + +typedef struct tnode *Tptr; +typedef struct tnode +{ + char splitchar; + Tptr lokid, eqkid, hikid; +} Tnode; +Tptr root; + +// Insert 1 -- Simple Insertion Algorithm + +Tptr insert1(Tptr p, char *s) +{ + if (p == 0) + { + p = (Tptr)malloc(sizeof(Tnode)); + p->splitchar = *s; + p->lokid = p->eqkid = p->hikid = 0; + } + if (*s < p->splitchar) + p->lokid = insert1(p->lokid, s); + else if (*s == p->splitchar) + { + if (*s != 0) + p->eqkid = insert1(p->eqkid, ++s); + } + else + p->hikid = insert1(p->hikid, s); + return p; +} + +void cleanup1(Tptr p) +{ + if (p) + { + cleanup1(p->lokid); + cleanup1(p->eqkid); + cleanup1(p->hikid); + free(p); + } +} + +// Insert 2 -- Faster version of Insert + +#define BUFSIZE 1000 +Tptr buf; +int bufn, freen; +void *freearr[10000]; +int storestring = 0; + +void insert2(char *s) +{ + int d; + char *instr = s; + + Tptr pp, *p; + p = &root; + while (pp = *p) + { + if ((d = *s - pp->splitchar) == 0) + { + if (*s++ == 0) + return; + p = &(pp->eqkid); + } + else if (d < 0) + p = &(pp->lokid); + else + p = &(pp->hikid); + } + for (;;) + { + // *p = (Tptr) malloc(sizeof(Tnode)); + if (bufn-- == 0) + { + buf = (Tptr)malloc(BUFSIZE * + sizeof(Tnode)); + freearr[freen++] = (void *)buf; + bufn = BUFSIZE - 1; + } + *p = buf++; + pp = *p; + pp->splitchar = *s; + pp->lokid = pp->eqkid = pp->hikid = 0; + if (*s++ == 0) + { + if (storestring) + pp->eqkid = (Tptr)instr; + return; + } + p = &(pp->eqkid); + } +} +void cleanup2() +{ + int i; + for (i = 0; i < freen; i++) + free(freearr[i]); +} + +// Search Algorithms + +int search1(char *s) +{ + Tptr p; + p = root; + while (p) + { + if (*s < p->splitchar) + p = p->lokid; + else if (*s == p->splitchar) + { + if (*s++ == 0) + return 1; + p = p->eqkid; + } + else + p = p->hikid; + } + return 0; +} + +int search2(char *s) +{ + int d, sc; + Tptr p; + sc = *s; + p = root; + while (p) + { + if ((d = sc - p->splitchar) == 0) + { + if (sc == 0) + return 1; + sc = *++s; + p = p->eqkid; + } + else if (d < 0) + p = p->lokid; + else + p = p->hikid; + } + return 0; +} + +// Advanced searching: Partial match, near words + +int nodecnt; +char *srcharr[100000]; +int srchtop; + +void pmsearch(Tptr p, char *s) +{ + if (!p) + return; + nodecnt++; + if (*s == '.' || *s < p->splitchar) + pmsearch(p->lokid, s); + if (*s == '.' || *s == p->splitchar) + if (p->splitchar && *s) + pmsearch(p->eqkid, s + 1); + if (*s == 0 && p->splitchar == 0) + srcharr[srchtop++] = + (char *)p->eqkid; + if (*s == '.' || *s > p->splitchar) + pmsearch(p->hikid, s); +} + +void nearsearch(Tptr p, char *s, int d) +{ + if (!p || d < 0) + return; + nodecnt++; + if (d > 0 || *s < p->splitchar) + nearsearch(p->lokid, s, d); + if (p->splitchar == 0) + { + if ((int)strlen(s) <= d) + srcharr[srchtop++] = + (char *)p->eqkid; + } + else + nearsearch(p->eqkid, *s ? s + 1 : s, + (*s == p->splitchar) ? d : d - 1); + if (d > 0 || *s > p->splitchar) + nearsearch(p->hikid, s, d); +} + + +#define NUMBER_OF_STRING 3 + +int main(int argc, char *argv[]) +{ + + char *arr[NUMBER_OF_STRING] = {"apple", "cat", "boy"}; + + ssort1main(arr, NUMBER_OF_STRING); + + for (int i = 0; i < NUMBER_OF_STRING; i++) + { + printf("%s ", arr[i]); + } +}