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 ) O(n) O(n)
- 最坏: O ( n 2 ) O(n^{2}) O(n2)
- 平均: O ( n + k ) O(n+k) O(n+k)
空间复杂度: O ( n ∗ k ) O(n*k) O(n∗k)
稳定性:稳定(也有说根据桶内排序决定稳定性)
到此这篇关于C语言排序算法之桶排序解析的文章就介绍到这了,更多相关C语言桶排序内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!