桶排序算法——C/C++

浅浅的花香味﹌ 2022-12-26 08:23 198阅读 0赞

桶排序

1. 算法思想

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

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

2. 实现原理

桶排序以下列程序进行:

  1. 设置一个定量的数组当作空桶子。
  2. 寻访序列,并且把项目一个一个放到对应的桶子去。
  3. 对每个不是空的桶子进行排序。
  4. 从不是空的桶子里把项目再放回原来的序列中。

3. 动态演示

在这里插入图片描述

(1)数据分桶
在这里插入图片描述
(2)桶内数据排序(大部分是在分桶时,即插入时就排序了)
在这里插入图片描述
(3)然后连接就好了

4. 完整代码

主要函数

  1. LN* Merge(LN* head, LN* list) 合并链表函数(也可以不需要)
  2. void insert(LN* list, int value) 顺序插入节点函数
  3. void BucketSort(int array[], int size, int num) 桶排序主程序
  4. int main() 主函数
  5. #define _CRT_SECURE_NO_WARNINGS
  6. #include <malloc.h>
  7. #include <stdio.h>
  8. typedef struct ListNode {
  9. int data;
  10. struct ListNode* next;
  11. } LN;
  12. // 输出线性表
  13. void displayL(LN* L) {
  14. LN* p = L; // p 指向首结点
  15. while (p != NULL) {
  16. // 不为空,依次遍历
  17. printf("%d ", p->data); // 打印
  18. p = p->next; // p 移向下一个节点
  19. }
  20. printf("\n");
  21. }
  22. // 输出数组
  23. void displayA(int* nums, int numsSize) {
  24. for (int i = 0; i < numsSize; i++) {
  25. printf("%d ", nums[i]);
  26. }
  27. printf("\n");
  28. }
  29. /***************************************************************************
  30. * @date 2020/12/03
  31. * @brief 合并链表
  32. * @param head 头指针
  33. * @param list 顺序数据链表
  34. ***************************************************************************/
  35. LN* Merge(LN* head, LN* list) {
  36. LN* last = head;
  37. last->next = list->next;
  38. while (last->next) {
  39. last = last->next;
  40. }
  41. return last;
  42. }
  43. /***************************************************************************
  44. * @date 2020/12/03
  45. * @brief 顺序插入节点
  46. * @param list 代表第几个桶的链表
  47. * @param value 数据
  48. ***************************************************************************/
  49. void insert(LN* list, int value) {
  50. LN* prev = list;
  51. LN* curr = list->next;
  52. LN* node = (LN*)malloc(sizeof(LN));
  53. node->data = value;
  54. node->next = NULL;
  55. if (curr == NULL) {
  56. prev->next = node;
  57. } else {
  58. while (curr != NULL && curr->data < value) {
  59. prev = curr;
  60. curr = curr->next;
  61. }
  62. prev->next = node;
  63. node->next = curr;
  64. }
  65. }
  66. /***************************************************************************
  67. * @date 2020/12/03
  68. * @brief 桶排序主程序
  69. * @param array 数组
  70. * @param size 数组大小
  71. * @param num 几个桶
  72. ***************************************************************************/
  73. void BucketSort(int array[], int size, int num) {
  74. // 申请内存,二级指针,初始化,可以理解头指针没数据,从下一个开始存数数据
  75. LN** buckets = (LN**)malloc(sizeof(LN*) * num);
  76. for (int i = 0; i < num; i++) {
  77. *(buckets + i) = (LN*)malloc(sizeof(LN));
  78. (*(buckets + i))->next = NULL;
  79. }
  80. // 1. 找到最大值和最小值求间隔(桶的大小)
  81. int max = array[0];
  82. int min = array[0];
  83. for (int i = 0; i < size; i++) {
  84. if (array[i] > max) {
  85. max = array[i];
  86. }
  87. if (array[i] < min) {
  88. min = array[i];
  89. }
  90. }
  91. int space = ((max - min) / num) + 1;
  92. // 2. 一个一个分桶排序
  93. for (int i = 0; i < size; i++) {
  94. int n = (array[i] - min) / space;
  95. insert(*(buckets + n), array[i]);
  96. }
  97. for (int i = 0; i < num; i++) {
  98. printf("第 %d 个桶数据: ", i);
  99. displayL((*(buckets + i))->next);
  100. }
  101. // // 3. 合并链表
  102. // LN* head = (LN*)malloc(sizeof(LN));
  103. // head->next = NULL;
  104. // LN* last = Merge(head, *(buckets + 0));
  105. // for (int i = 1; i < num; i++) {
  106. // if ((*(buckets + i))->next) {
  107. // last = Merge(last, *(buckets + i));
  108. // }
  109. // }
  110. // head = head->next;
  111. // // 4. 把链表值返回数组
  112. // for (int i = 0; i < size; i++) {
  113. // array[i] = head->data;
  114. // head = head->next;
  115. // }
  116. // 3+4. 当然也可以不合并链表,直接把数据返回数组
  117. int index = 0;
  118. for (int i = 0; i < num; i++) {
  119. if ((*(buckets + i))->next != NULL) {
  120. LN* temp = (*(buckets + i))->next;
  121. while (temp != NULL) {
  122. array[index++] = temp->data;
  123. temp = temp->next;
  124. }
  125. }
  126. }
  127. }
  128. int main() {
  129. int array[] = {
  130. 49, 65, 97, 76, 13, 49, 10, 8, 21};
  131. int size = sizeof(array) / sizeof(int);
  132. int BUCKETNUM = 5;
  133. // 打印原始数据
  134. printf("%d \n", size);
  135. displayA(array, size);
  136. BucketSort(array, size, BUCKETNUM);
  137. displayA(array, size);
  138. return 0;
  139. }

5. 结果展示

在这里插入图片描述

6. 算法分析

时间复杂度:

  1. 最好: O ( n ) O(n) O(n)
  2. 最坏: O ( n 2 ) O(n^{2}) O(n2)
  3. 平均: O ( n + k ) O(n+k) O(n+k)

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

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

7. 参考资料

[1] 【算法】排序算法之桶排序——使用动态图
[2] Bucket sort——维基百科,仿写 C 代码
[3] 动态演示 ——数据结构动态演示网站

发表评论

表情:
评论列表 (有 0 条评论,198人围观)

还没有评论,来说两句吧...

相关阅读

    相关 排序算法 - 排序

    前言 桶排序(Bucket sort)或所谓的箱排序,是一个排序算法,工作的原理是将数组分到有限数量的桶里。每个桶再个别排序(有可能再使用别的排序算法或是以递归方式继续使

    相关 算法排序

    计数排序、桶排序、基数排序均为O(n)算法 桶排序可以看成是计数排序的升级版,它将要排的数据分到多个有序的桶里,每个桶里的数据再单独排序,再把每个桶的数据依次取出,即可

    相关 排序算法-排序

    先创建若干个桶,每个桶存放不同范围的数据 桶和桶之间的跨度=(数据最大值-数据最小值)/ (桶的数量 - 1) 假设有一个数组:1.2,0.5,4.5,2.6,2.7

    相关 [算法]排序

    介绍 桶排序是分治算法的应用. 桶排序实际上就是把要排序的容器中的数据,分别按照大小跨度 分散在若干个桶中,如果桶中有一个以上的数据,则单独的桶进行 排序,最