C 语言

关注公众号 jb51net

关闭
首页 > 软件编程 > C 语言 > C语言桶排序

C语言排序算法之桶排序解析

作者:有人_295

这篇文章主要介绍了C语言排序算法之桶排序解析,桶排序Bucket sort或所谓的箱排序,是一个排序算法,工作的原理是将数组分到有限数量的桶里,每个桶再分别排序,大部分是在分桶时,即插入时就排序了,需要的朋友可以参考下

1. 算法思想

桶排序(Bucket sort)或所谓的箱排序,是一个排序算法,工作的原理是将数组分到有限数量的桶里,每个桶再分别排序(大部分是在分桶时,即插入时就排序了)。

个人理解,适合数据比较集中排序,桶的数量适当设置。

2. 实现原理

桶排序以下列程序进行:

3. 动态演示

在这里插入图片描述

(1)数据分桶

在这里插入图片描述

(2)桶内数据排序(大部分是在分桶时,即插入时就排序了)

在这里插入图片描述

(3)然后连接就好了

4. 完整代码

主要函数

插入函数:void insert(BN* list, int value)
排序函数:void bucket_sort(int* array, int size, int num)
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h> // rand() srand()
#include <time.h>   // time()

typedef struct BucketNode
{
    int                data;
    struct BucketNode* next;
} BN;

void displayL(BN* L);               // 输出链表
void display(int* array, int size); // 输出数组
int  check(int* array, int size);   // 检查函数

/***************************************************************************
 * @date    2020/12/03
 * @brief   合并链表
 * @param   head    头指针
 * @param   list    顺序数据链表
 ***************************************************************************/
BN* merge(BN* head, BN* list)
{
    BN* last   = head;
    last->next = list->next;
    while (last->next) {
        last = last->next;
    }
    return last;
}

/***************************************************************************
 * @date    2020/12/03
 * @brief   顺序插入节点
 * @param   list    代表第几个桶的链表
 * @param   value   数据
 ***************************************************************************/
void insert(BN* list, int value)
{
    BN* prev   = list;
    BN* curr   = list->next;
    BN* node   = (BN*)malloc(sizeof(BN));

    node->data = value;
    node->next = NULL;
    if (curr == NULL) {
        prev->next = node;
    } else {
        while (curr != NULL && curr->data < value) {
            prev = curr;
            curr = curr->next;
        }
        prev->next = node;
        node->next = curr;
    }
}

/***************************************************************************
 * @date    2020/12/03
 * @brief   桶排序主程序
 * @param   array   数组
 * @param   size    数组大小
 * @param   num     几个桶
 ***************************************************************************/
void bucket_sort(int* array, int size, int num)
{
    // 申请内存,二级指针,初始化,可以理解头指针没数据,从下一个开始存数数据
    BN** buckets = (BN**)malloc(sizeof(BN*) * num);
    for (int i = 0; i < num; i++) {
        *(buckets + i)         = (BN*)malloc(sizeof(BN));
        (*(buckets + i))->next = NULL;
    }

    // 1. 找到最大值和最小值求间隔(桶的大小)
    int max = array[0];
    int min = array[0];
    for (int i = 0; i < size; i++) {
        if (array[i] > max) {
            max = array[i];
        }
        if (array[i] < min) {
            min = array[i];
        }
    }
    int space = ((max - min) / num) + 1;

    // 2. 一个一个分桶排序
    for (int i = 0; i < size; i++) {
        int n = (array[i] - min) / space;
        insert(*(buckets + n), array[i]);
    }
    for (int i = 0; i < num; i++) {
        printf("第 %d 个桶数据: ", i);
        displayL((*(buckets + i))->next);
    }

    // // 3. 合并链表
    // BN* head   = (BN*)malloc(sizeof(BN));
    // head->next = NULL;
    // BN* last   = merge(head, *(buckets + 0));
    // for (int i = 1; i < num; i++) {
    //     if ((*(buckets + i))->next) {
    //         last = merge(last, *(buckets + i));
    //     }
    // }
    // head = head->next;

    // // 4. 把链表值返回数组
    // for (int i = 0; i < size; i++) {
    //     array[i] = head->data;
    //     head     = head->next;
    // }

    // 3+4. 当然也可以不合并链表,直接把数据返回数组
    int index = 0;
    for (int i = 0; i < num; i++) {
        if ((*(buckets + i))->next != NULL) {
            BN* temp = (*(buckets + i))->next;
            while (temp != NULL) {
                array[index++] = temp->data;
                temp           = temp->next;
            }
        }
    }
}

int main()
{
    // 测试用例
    // int array[]    = {49, 38, 65, 97, 76, 13, 27, 49, 10};
    // int array_size = sizeof(array) / sizeof(array[0]);
    // int bucket_num = 5;
    // printf("%d \n", array_size);
    // printf("排序前数组:");
    // display(array, array_size);
    // bucket_sort(array, array_size, bucket_num);
    // printf("排序后数组:");
    // display(array, array_size);

    // 随机测试
    int bucket_num = 5;              // 桶的个数
    int array_num  = 20;             // 数组数量
    int array_size = 20;             // 数组大小
    int array[array_size];           // 数组初始化
    srand((unsigned int)time(NULL)); // 随机数种子,保证每次不一样
    for (int i = 0; i < array_num; i++) {
        for (int j = 0; j < array_size; j++) {
            array[j] = rand() % 1000; // 随机生成数大小 0~999
        }
        printf("原来的数组:");
        display(array, array_size);
        bucket_sort(array, array_size, bucket_num);
        printf("排序后数组:");
        display(array, array_size);
        // 检测排序结果
        if (check(array, array_size) != 0) {
            exit(-1);
        }
        printf("\n");
    }

    return 0;
}

/***************************************************************************
 * @date    2020/12/03
 * @brief   输出线性表
 * @param   L   首节点
 ***************************************************************************/
void displayL(BN* L)
{
    BN* p = L;                  // p 指向首结点
    while (p != NULL) {         // 不为空,依次遍历
        printf("%d ", p->data); // 打印
        p = p->next;            // p 移向下一个节点
    }
    printf("\n");
}

/***************************************************************************
 * @date    2020/12/03
 * @brief   输出数组
 * @param   array   数组
 * @param   size    数组大小
 ***************************************************************************/
void display(int* array, int size)
{
    for (int i = 0; i < size; i++) {
        printf("%d ", array[i]);
    }
    printf("\n");
}

/**
 * @brief 检查函数,从小到大
 *
 * @param array        数组首指针
 * @param size         数组大小
 */
int check(int* array, int size)
{
    for (int i = 0; i < size - 1; i++) {
        if (array[i] > array[i + 1]) {
            printf("sort array fail...\n");
            return -1;
        }
    }
    printf("sort array success...\n");
    return 0;
}

5. 结果展示

在这里插入图片描述

6. 算法分析

时间复杂度:

空间复杂度: O ( n ∗ k ) O(n*k) O(n∗k)

稳定性:稳定(也有说根据桶内排序决定稳定性)

到此这篇关于C语言排序算法之桶排序解析的文章就介绍到这了,更多相关C语言桶排序内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文