This is a kind of bogosort. It surely succeed unless malloc() returns NULL. It is a stable sort.
The idea: We try to sort a[ ] of size N. Let c[ ] be a permutation of {0, 1, ..., N-1}. There exists at least one permutation such that a[c[i]] is sorted.
#include <stdio.h> #include <stdlib.h> #include <time.h> #define VERBOSE #define N 4 /* the size of the array to be sorted */ int a[N]; /* the array to be sorted */ int c[N]; /* a permutation of 0, 1, 2, ..., N-1 */ void init(void); int issorted(void); int next(void); void swap(int i, int j); void sort(void); int main() { int i; srand((unsigned)time(NULL)); /* initialize a[ ] by rand() */ printf("-- before --\n"); for (i = 0; i < N; i++) { a[i] = rand() % 9 + 1; printf(" %2d", a[i]); } putchar('\n'); for (init(); issorted() != 1; next()) { /* main loop */ ; } sort(); printf("-- after --\n"); for (i = 0; i < N; i++) { printf(" %2d", a[i]); } putchar('\n'); } /* initialize c[ ] by 0, 1, 2, ..., N-1 */ void init(void) { int i; for (i = 0; i < N; i++) { c[i] = i; } } /* if a[c[i]] <= a[c[i+1]] for every i, returns 1, else 0 */ int issorted(void) { int i; #ifdef VERBOSE for (i = 0; i < N; i++) { printf("%x", c[i]); } for (i = 0; i < N; i++) { printf(" %2d", a[c[i]]); } putchar('\n'); #endif for (i = 0; i < N-1 && a[c[i]] <= a[c[i+1]]; i++) { ; } return i == N-1 ? 1 : 0; } /* changes c[ ] to the next permutation in the lexicographic order. */ /* return value: 1 ... success, 0 ... failure (if no next permutation). */ /* */ /* example: assume that c[ ] is "035421". Note that 3 < 5 > 4 > 2 > 1. */ /* (We use the notation in mathematics, not in C.) First, search for 3.*/ /* Then, search for 4. Exchanging them, we have "0345321". Revease */ /* "5321" to "1235". Then, we have "041235". This is the next */ /* permutation. */ int next(void) { int i, j; for (i = N-1; i > 0 && c[i-1] > c[i]; i--) { /* search for 3 */ ; } if (i == 0) { return 0; } for (j = i; j < N && c[j] > c[i-1]; j++) { /* search for 4 */ ; } swap(i-1, j-1); /* exchange 3 and 4 */ for (j = N-1; i < j; i++, j--) { /* reverse "5321" to "1235" */ swap(i, j); } return 1; } void swap(int i, int j) { int tmp = c[i]; c[i] = c[j]; c[j] = tmp; } /* sort a[ ] according to c[ ]. */ /* if a[ ] is "6139", then c[ ] is 1203. */ /* a[i] becomes "1369". */ void sort(void) { const int done = -1; int start, i; int tmp; while (1) { for (start = 0; start < N && c[start] == done; start++) { ; } if (start == N) { return; } if (c[start] == start) { c[start] = done; continue; } tmp = a[start]; i = start; while (c[i] != start) { int i_prev = i; a[i] = a[c[i]]; i = c[i]; c[i_prev] = done; } a[i] = tmp; c[i] = done; } }
main.c, bogosort.c, and bogosort.h. Compile by "cc main.c bogosort.c".
main.c
#include <stdio.h> #include <stdlib.h> #include <time.h> #include "bogosort.h" #define N 12 /* the size of the each element of the array to be sorted */ struct object { int r; double n; /* there is no reason to use double, instead of int. */ }; struct object a[N]; /* the array to be sorted */ int compare(const void *p, const void *q); int main(int argc, char *argv[]) { int i; time_t t0, t1; if (argc == 1) { /* if there is no command line option */ srand((unsigned)time(NULL)); for (i = 0; i < N; i++) { a[i].r = rand() % 9 + 1; /* initialize a[ ] by rand() */ a[i].n = i; } } else { /* if there is command line options */ for (i = 0; i < N; i++) { a[i].r = N-1-i; /* initialize a[ ] for the worst case */ a[i].n = i; } } printf("-- before --\n"); for (i = 0; i < N; i++) { /* print a[ ] */ printf("%2d ", a[i].r); } putchar('\n'); for (i = 0; i < N; i++) { printf("%2.0f ", a[i].n); } putchar('\n'); t0 = time(NULL); bogosort(a, N, sizeof(struct object), compare); t1 = time(NULL); printf("-- after --\n"); for (i = 0; i < N; i++) { /* print a[ ] */ printf("%2d ", a[i].r); } putchar('\n'); for (i = 0; i < N; i++) { printf("%2.0f ", a[i].n); } putchar('\n'); printf("%f sec.\n", difftime(t1, t0)); } int compare(const void *p, const void *q) { return ((struct object *)p)->r - ((struct object *)q)->r; }
bogosort.c.
#include <stdio.h> #include <stdlib.h> #include "bogosort.h" int *c; /* the address to the array of a permutation of 0 to N-1 */ int *d; /* a copy of c[ ] */ static void init(int n); static int issorted(void *base, size_t n, size_t size, int (*comp)(const void *, const void *)); static int next(int *p, int n); static void swap(int *p, int i, int j); static void sort(void *base, size_t n, size_t size); int bogosort(void *base, size_t n, size_t size, int (*comp)(const void *, const void *)) { int i, tmp; c = malloc((sizeof(int)) * n); if (c == NULL) { /* not enough memory */ return 0; /* failure */ } d = malloc((sizeof(int)) * n); if (d == NULL) { /* not enough memory */ free(c); return 0; /* failure */ } for (init(n); issorted(base, n, size, comp) != 1; next(c, n)) { ; } sort(base, n, size); free(d), free(c); return 1; /* success */ } /* initialize c[ ] */ static void init(int n) { int i; for (i = 0; i < n; i++) { c[i] = i; } } static int issorted(void *base, size_t n, size_t size, int (*comp)(const void *, const void *)) { int i; for (i = 0; i < n-1 && (*comp)((char *)base + c[i] * size, (char *)base + c[i+1] * size) <= 0; i++) { ; } return i == n-1 ? 1 : 0; } static int next(int *p, int n) { int i, j; for (i = n-1; i > 0 && p[i-1] > p[i]; i--) { ; } if (i == 0) { return 0; } for (j = i; j < n && p[j] > p[i-1]; j++) { ; } swap(p, i-1, j-1); for (j = n-1; i < j; i++, j--) { swap(p, i, j); } return 1; } static void swap(int *p, int i, int j) { int tmp = p[i]; p[i] = p[j]; p[j] = tmp; } static void sort(void *base, size_t n, size_t size) { const int done = -1; int start, j, i; char tmp; for (j = 0; j < size; j++) { for (i = 0; i < n; i++) { d[i] = c[i]; } while (1) { for (start = 0; start < n && d[start] == done; start++) { ; } if (start == n) { break; } if (d[start] == start) { d[start] = done; continue; } tmp = ((char *)base)[start * size + j]; i = start; while (d[i] != start) { int i_prev = i; ((char *)base)[i * size + j] = ((char *)base)[d[i] * size + j]; i = d[i]; d[i_prev] = done; } ((char *)base)[i * size + j] = tmp; d[i] = done; } } }
bogosort.h
int bogosort(void *base, size_t n, size_t size, int (*comp)(const void *, const void *)); /* almost same as qsort(). It returns 1 if secceeded, 0 if failed. */ /* malloc() is used in this funcion. */
This is an Ο(N*N!) algorithm.
N | T | T/(N*N!) |
---|---|---|
12 | 12 sec | 2.0876756987868098979210090321201e-9 |
13 | 153 sec | 1.8900259284874669490054105438721e-9 |
14 | 2157 sec | 1.7673141610216440148412937528584e-9 |
N | T |
---|---|
15 | 9.629 hours |
16 | 6.874 days |
17 | 123.7 days |
18 | 2357 days |
19 | 129.4 years |
20 | 2725 years |
You must be patient to use this program!