資料結構與演算法分析(c 語言描述)基數排序 陣列實現

jerrkill發表於2018-12-20
/**
 * 基數排序陣列實現
 * 思路:
 * 基數排序是一個 分配-收集 的過程
 * 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");
}

結果截圖
file

高度自律,深度思考,以勤補拙

相關文章