Considérez le tableau d'entrée comme deux partitions. La première est une liste triée de tous les mots avec le bit de tête 0. La seconde est la même chose avec le bit de tête 1. Ces bits sont tournés vers la position la plus à droite. Ce qui reste est deux listes triées. Une seule passe de fusion les trie.
#include <stdio.h>
#include <stdlib.h>
void rotate_and_resort(unsigned *a, int n) {
// rotate
for (int i = 0; i < n; ++i) a[i] = (a[i] << 1) | (a[i] >> 31);
// resort; find the first word with rightmost bit 1
int rm1;
for (rm1 = 0; rm1 < n && (a[rm1] & 1) == 0; ++rm1) /* skip */;
// If all the words end with the same bit, we're done.
if (rm1 == 0 || rm1 == n) return;
// make a temp copy for merging
unsigned t[n];
for (int i = 0; i < n; ++i) t[i] = a[i];
// merge
int i = 0, j = rm1, k = 0;
while (k < n)
a[k++] = i < rm1 && t[i] < t[j] ? t[i++] : t[j++];
}
int cmp_unsigned(const void *va, const void *vb) {
unsigned a = *(unsigned*)va, b = *(unsigned*)vb;
return a > b ? 1 : a < b ? -1 : 0;
}
int main(void) {
unsigned n = 100, a[n];
for (int i = 0; i < n; ++i) a[i] = rand() ^ (rand() << 16);
qsort(a, n, sizeof *a, cmp_unsigned);
rotate_and_resort(a, n);
for (int i = 0; i < n; ++i) printf("%u\n", a[i]);
return 0;
}
Il existe un algorithme de fusion plus sophistiqué où l'espace temporaire est au plus égal à la moitié de la taille de l'entrée. Ici j'ai utilisé l'algorithme le plus simple, qui fait une copie complète.