/**
* 基數排序陣列實現
* 思路:
* 基數排序是一個 分配-收集 的過程
* N--需要排序的個數 radix-基數 pos_len 位數
* 其中用二維陣列來表示桶[j][N].j-桶位,B[j][0]:分配的元素個數,B[j][1~N]:分配的元素
* 然後在收集到原陣列中,再重複上面動作指導到達 pos_len 的最高位,排序完畢
* 以空間換時間的思想
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define Error(Str) FatalError(Str)
#define FatalError(Str) fprintf(stderr,"%s\n",Str),exit(1)
// #define DEBUG 1
#define N 10 //要排序的數個數
#define RADIX 12 // 基數 進位制
#define BUCKET_LEN 12 //桶的長度 桶長=基數
#define POS_LEN 4 //位數
void radix_sort(int *pArr, int n, int _radix, int bucket_len, int pos_len);
int get_num_in_pos(int num, int pos, int _radix);
void print_arr(int arr[], int n);
void print_bucket(int *arr, int n);
void test();
int main(void)
{
test();
return 0;
}
/**
* 基數排序核心
* @param pArr 需要排序陣列的指標
* @param n 數的個數
* @param _radix 基數
* @param bucket_len 桶長
* @param pos_len 位長
*/
void radix_sort(int *pArr, int n, int _radix, int bucket_len, int pos_len)
{
int pos;
int *bucket[bucket_len];
for (int i = 0; i < bucket_len; i++) {
bucket[i] = (int*)malloc(sizeof(int) * n + 1); //可能該位上的所有數相同
if (NULL == bucket[i])
FatalError("out of space");
bucket[i][0] = 0; //記錄該桶上的數個數
}
for (pos = 1; pos <= pos_len; pos++) {
//分配
for (int i = 0; i < n; i++) {
int num_in_pos = get_num_in_pos(pArr[i], pos, _radix);
int index = ++bucket[num_in_pos][0];
bucket[num_in_pos][index] = pArr[i];
}
// 格式化輸出桶,過程更形象直觀
#ifdef DEBUG
int *arr1[n];
for (int i = 0; i < n; i++) {
arr1[i] = (int*)malloc(sizeof(int) * (bucket_len - 1) );
if (NULL == bucket[i])
FatalError("out of space");
}
for (int i = 0; i < bucket_len; i++) {
for (int j = 1; j <= bucket[i][0]; j++) {
arr1[j-1][i] = bucket[i][j];
}
}
printf("第%d位\n", pos);
for (int i = n - 1; i >= 0 ; i--) {
int count = 0, t_count = 0;
for (int j = 0; j < bucket_len; j++) {
if (arr1[i][j]) {
count++;
if (t_count) {
for (int k = 0; k <= j - t_count; k++)
printf("\t");
} else {
for (int k = 0; k <= j; k++)
printf("\t");
}
printf("%d ", arr1[i][j]);
t_count = j + 1;
}
}
if (count > 0)
printf("\n");
}
for (int i = 0; i < bucket_len; i++) {
printf("\t%d", i);
}
printf("\n");
#endif
//收集
int k = 0; //pArr索引
for (int i = 0; i < bucket_len; i++) {
for (int j = 1; j <= bucket[i][0]; j++)
pArr[k++] = bucket[i][j];
bucket[i][0] = 0; //重置次數
}
#ifdef DEBUG
printf("\n");
print_arr(pArr, n);
#endif
}
}
/**
* 根據基數跟位數獲取當前位上的數值
* @param num 數
* @param pos 第幾位數
* @param _radix 基數
* @return pos位上的數
*/
int get_num_in_pos(int num, int pos, int _radix)
{
int temp = 1;
for (int i = 0; i < pos - 1; i++)
temp *= _radix;
return (num / temp) % _radix;
}
void test()
{
int i, arr[N];
srand((unsigned)time(NULL));
int max = 1;
for (i = 0; i <= POS_LEN - 1; i++)
max *= RADIX;
for (i = 0; i < N; i++) {
arr[i] = rand() % max;
}
printf("get a random intger array\n");
print_arr(arr, N);
printf("\tafter sort\n");
radix_sort(arr, N, RADIX, BUCKET_LEN, POS_LEN);
print_arr(arr, N);
}
void print_arr(int arr[], int n)
{
for (int i = 0; i < n; i++)
printf("\t%d", arr[i]);
printf("\n");
}
結果截圖