基数排序,一种很费内存但是快得一塌糊涂的排序算法。
测试用例为两千万的int数组,使用随机数生成器生成整个数组的数值,测试结果为:
堆排序14.8秒;
qsort库函数6.4秒;
归并排序4.4秒;
快速排序版本1为2.7秒;
快速排序版本2为2.7秒;
二进制快速排序为4.8秒;
基数排序为0.95秒,大比分领先于其他常见排序算法。
附:测试代码如下(gcc -O3 test.c -o test.exe)
#include <stdio.h> #include <stdlib.h> #include <time.h> #include <limits.h> #include <string.h> #include <windows.h> #define NUMS 20000000 void maxHeapify(int a[], int i, int n) { int j, temp; while(2*i + 1 < n) { j = 2*i + 1; if(j + 1 < n && a[j] < a[j+1]) { ++j; } if(a[i] >= a[j]) { break; } temp = a[i]; a[i] = a[j]; a[j] = temp; i = j; } } void generateMaxHeap(int h[], int n) { int i; for(i = n/2 - 1; i >= 0; --i) { maxHeapify(h, i, n); } } void heapSort(int h[], int n) { int temp; generateMaxHeap(h, n); while(n > 1) { temp = h[0]; h[0] = h[n - 1]; h[n - 1] = temp; --n; maxHeapify(h, 0, n); } } int bigRand() { int i = rand() * (RAND_MAX + 1) + rand(); return i; } int intCmp(const void *a, const void *b) { return *(int*)(a) - *(int*)(b); } void merge(int a[], int p, int m, int r) { int *cl = (int*)malloc((m + 2 - p)* sizeof(int)), *cr = (int*)malloc((r - m + 1)* sizeof(int)), i, j = 0, k = 0; cl[m + 1 - p] = INT_MAX; cr[r - m] = INT_MAX; memcpy(cl, &a[p], (m + 1 - p)* sizeof(int)); memcpy(cr, &a[m + 1], (r - m)* sizeof(int)); for(i = 0; i < r - p + 1; ++i) { if(cl[j] <= cr[k]) { a[p + i] = cl[j++]; } else { a[p + i] = cr[k++]; } } free(cl), free(cr); } void insertionSort(int a[], int n) { int e, i, j; for(i = 1; i < n; ++i) { e = a[i]; j = i; while(j > 0 && a[j - 1] > e) { a[j] = a[j - 1]; --j; } a[j] = e; } } void mergeSort(int a[], int p, int r) { if(r - p < 23) { insertionSort(&a[p], r - p + 1); return; } int m = p + (r - p) / 2; mergeSort(a, p, m); mergeSort(a, m + 1, r); merge(a, p, m, r); } int partition(int a[], int p, int r) { int i = p, j, e = a[p], temp; for(j = p + 1; j <= r; ++j) { if(a[j] < e) { ++i; temp = a[i]; a[i] = a[j]; a[j] = temp; } } a[p] = a[i]; a[i] = e; return i; } int hoarePartition(int a[], int p, int r) { int i = p - 1, j = r, e = a[r], temp; while(1) { while(a[++i] < e); while(a[--j] > e) { if(j == p) { break; } } if(i >= j) { break; } temp = a[i]; a[i] = a[j]; a[j] = temp; } a[r] = a[i]; a[i] = e; return i; } void quickSort(int a[], int p, int r) { if(r - p < 23) { insertionSort(&a[p], r - p + 1); return; } int m = partition(a, p, r); quickSort(a, p, m - 1); quickSort(a, m + 1, r); } void quickSortWithHoarePartition(int a[], int p, int r) { if(r - p < 23) { insertionSort(&a[p], r - p + 1); return; } int m = hoarePartition(a, p, r); quickSortWithHoarePartition(a, p, m - 1); quickSortWithHoarePartition(a, m + 1, r); } void bubbleSort(int a[], int n) { int i, j, temp; for(i = 1; i < n; ++i) { for(j = 0; j < n - i; ++j) { if(a[j] > a[j + 1]) { temp = a[j]; a[j] = a[j+1]; a[j+1] = temp; } } } } #define BPW 32 int digit(int i, int w) { i >>= w; return i & 1; } void binaryQuickSort(int a[], int p, int r, int w) { int i = p, j = r, temp; if(p >= r || w < 0) { return; } while(1) { while(!digit(a[i], w) && i < j) { ++i; } while(digit(a[j], w) && i < j) { --j; } if(i == j) { break; } temp = a[i]; a[i] = a[j]; a[j] = temp; } if(!digit(a[i], w)) { ++i; } binaryQuickSort(a, p, i - 1, w - 1); binaryQuickSort(a, i, r, w - 1); } #define BPR 8 int getRadix(int num, int w) { return (num>>(BPR*w)) & ((1<<BPR)-1); } void radixLSD(int a[], int n) { int i, w, count[1<<BPR], *copy = (int*)malloc((n)*sizeof(int)), pos; for(w = 0; w < BPW/BPR; ++w) { memcpy(copy, a, n*sizeof(int)); memset(count, 0, sizeof(count)); for(i = 0; i < n; ++i) { ++count[getRadix(a[i], w)]; } for(i = 1; i < 1<<BPR; ++i) { count[i] += count[i-1]; } for(i = n-1; i >= 0; --i) { pos = --count[getRadix(copy[i], w)]; a[pos] = copy[i]; } } free(copy); } int main() { unsigned t1, t2; srand(time(0)); int *a = (int*)malloc(NUMS * sizeof(int)), i; for(i = 0; i < NUMS; ++i) { a[i] = bigRand(); } t1 = GetTickCount(); heapSort(a, NUMS); t2 = GetTickCount(); printf("heapSort took %ums\n", t2 - t1); for(i = 0; i < NUMS; ++i) { a[i] = bigRand(); } t1 = GetTickCount(); qsort(a, NUMS, sizeof(int), intCmp); t2 = GetTickCount(); printf("qsort took %ums\n", t2 - t1); for(i = 0; i < NUMS; ++i) { a[i] = bigRand(); } t1 = GetTickCount(); mergeSort(a, 0, NUMS - 1); t2 = GetTickCount(); printf("mergeSort took %ums\n", t2 - t1); for(i = 0; i < NUMS; ++i) { a[i] = bigRand(); } t1 = GetTickCount(); quickSort(a, 0, NUMS - 1); t2 = GetTickCount(); printf("quickSort took %ums\n", t2 - t1); for(i = 0; i < NUMS; ++i) { a[i] = bigRand(); } t1 = GetTickCount(); quickSortWithHoarePartition(a, 0, NUMS - 1); t2 = GetTickCount(); printf("quickSortWithHoarePartition took %ums\n", t2 - t1); for(i = 0; i < NUMS; ++i) { a[i] = bigRand(); } t1 = GetTickCount(); binaryQuickSort(a, 0, NUMS - 1, BPW - 1); t2 = GetTickCount(); printf("binaryQuickSort took %ums\n", t2 - t1); for(i = 0; i < NUMS; ++i) { a[i] = bigRand(); } t1 = GetTickCount(); radixLSD(a, NUMS); t2 = GetTickCount(); printf("radixLSD took %ums\n", t2 - t1); /* for(i = 0; i < NUMS; ++i) { printf("%d\n", a[i]); } */ free(a); return 0; }

浙公网安备 33010602011771号