• 数据结构 桶排序 基数排序


    首先来了解桶排序

    将数组分成若干类  分这个类的条件  我们自己决定

    这里我们用的是 每隔5个数分为一类

    如20~24  25~29 30~34...

    数组中的元素满足这样的条件就会被放在相应的桶中

    如: 23会被放在20~24的桶中

    假设我们有这样一个数组

    int arr[15] = { 34,36,31,78,65,32,33,34,89,90,91,67,52,71,77};

    我们决定桶的数量 为确保数组中的元素都能如桶   

    一般设定为  :

    原数组中的最大值-最小值+1 

    想判断当前数组元素应该入哪个桶  我们这里的条件是:

    当前元素的值-最小值/5   为他要入的桶的下标

    如  最小元素20 当前元素40  那么他要进去的桶的下标为 (40-20)/5=4

    我们这里所谓的桶  其实就是一个哈希数组 

    这里用的是链式存储法 (每一个元素都是一个链表的头)

    如相应的桶  就是 把元素添加到哈希数组的相应下标上的链表上去  在这里我们添加用的是

    链表插入的方式  直接根据节点的值将节点插入到相应的位置   完成排序 

    之后我们只需要 遍历哈希数组并遍历哈希数组元素  吧 哈希数组中的元素都放回到原数组中去

    这样就实现了桶排序

    桶排序完整代码如下

    1. #include
    2. using namespace std;
    3. #define jiange 5
    4. struct List
    5. {
    6. int id;
    7. List* pNext;
    8. };
    9. void Insert(List*&pHead,int value)
    10. {
    11. List* pTemp=new List;
    12. pTemp->id = value;
    13. pTemp->pNext = NULL;
    14. //链表中没有节点
    15. if (pHead == NULL)
    16. {
    17. pHead = pTemp;
    18. return;
    19. }
    20. //链表中的头节点比当前节点的值大
    21. //头插入
    22. if (pTemp->id < pHead->id)
    23. {
    24. pTemp->pNext=pHead;
    25. pHead = pTemp;
    26. return;
    27. }
    28. //链表的头的值比当前要插入的节点的值小
    29. //遍历链表 找到要插在谁的后面
    30. List* pMark = pHead;
    31. while (pMark->pNext != NULL)
    32. {
    33. if (pMark->pNext->id > pTemp->id)
    34. {
    35. pTemp->pNext = pMark->pNext;
    36. pMark->pNext = pTemp;
    37. return;
    38. }
    39. pMark = pMark->pNext;
    40. }
    41. //遍历到最后一个节点 都没找到比当前节点大的节点 插在最后
    42. pMark->pNext = pTemp;
    43. }
    44. void BuckeSort(int arr[],int nLen)
    45. {
    46. int begin = arr[0];
    47. int end =arr[0];
    48. //参数校验
    49. if (arr == NULL || nLen <= 10)
    50. {
    51. return;
    52. }
    53. //找到最大值和最小值确定桶的数量
    54. for (int i = 0; i < nLen; i++)
    55. {
    56. if (arr[i] < begin)
    57. begin = arr[i];
    58. if (arr[i] > end)
    59. end = arr[i];
    60. }
    61. int nBucketCount = end -begin + 1;
    62. //开辟空间
    63. List** Hash = new List*[nBucketCount];
    64. ::memset(Hash, 0, sizeof(List*)* nBucketCount);
    65. //遍历数组入桶
    66. for (int i = 0; i < nLen; i++)
    67. {
    68. //入桶函数
    69. Insert(Hash[(arr[i]-begin)/jiange], arr[i]);
    70. }
    71. //出桶
    72. int j = 0;
    73. for (int i = 0; i < nBucketCount; i++)
    74. {
    75. while (Hash[i])
    76. {
    77. List* pDel = Hash[i];
    78. Hash[i] = Hash[i]->pNext;
    79. arr[j++] =pDel->id;
    80. delete pDel;
    81. pDel = NULL;
    82. }
    83. }
    84. delete Hash;
    85. Hash = NULL;
    86. }
    87. int main()
    88. {
    89. int arr[15] = { 34,36,31,78,65,32,33,34,89,90,91,67,52,71,77};
    90. BuckeSort(arr, 15);
    91. for (int val : arr)
    92. {
    93. cout << val << " ";
    94. }
    95. return 0;
    96. }

    基数排序:

    可以看做是桶排序的另一种优化  只不过 他的如桶条件变了 

    而且需要额外创建一个记录链表的尾的哈希数组;  用于添加节点

    尾入  头出

    思想:

    先把数组中的元素根据个位入桶

    出桶放入原数组

    在把数组中的元素根据十位入桶

    出桶放入原数组...

    直到把数组中的元素根据  数组中的最大的元素的最高位  入桶

    出桶放入原数组   结束

    这样一来  数组自己就排序好了

    基数排序:

    代码如下

    1. #include
    2. using namespace std;
    3. #define jiange 5
    4. struct List
    5. {
    6. int id;
    7. List* pNext;
    8. };
    9. void AddNode(List*& pHead, List*& pEnd ,int value)
    10. {
    11. List* pTemp = new List;
    12. pTemp->id = value;
    13. pTemp->pNext = NULL;
    14. //链表中没有节点
    15. if (pHead == NULL)
    16. {
    17. pHead = pTemp;
    18. }
    19. //链表有节点
    20. //尾插入
    21. else
    22. {
    23. pEnd->pNext = pTemp;
    24. }
    25. pEnd = pTemp;
    26. }
    27. void RadixSort(int arr[], int nLen)
    28. {
    29. //参数校验
    30. if (arr == NULL || nLen <= 10)
    31. {
    32. return;
    33. }
    34. //找到最大值
    35. int max = arr[0];
    36. for (int i = 0; i < nLen; i++)
    37. {
    38. if (arr[i] > max)
    39. {
    40. max = arr[i];
    41. }
    42. }
    43. int base = 1;
    44. //创建桶中链表的头节点数组
    45. List** pHeadarr = new List * [10];
    46. //创建桶中链表的尾节点数组
    47. List** pEndarr = new List * [10];
    48. ::memset(pHeadarr, 0, sizeof(List*) * 10);
    49. ::memset(pEndarr, 0, sizeof(List*) * 10);
    50. while (max / base != 0)
    51. {
    52. //arr的元素放入桶中
    53. for (int i = 0; i < nLen; i++)
    54. {
    55. //链表尾部添加
    56. AddNode(pHeadarr[arr[i] / base % 10], pEndarr[arr[i] / base % 10], arr[i]);
    57. }
    58. //出桶
    59. int j = 0;
    60. for (int i = 0; i < 10; i++)
    61. {
    62. while (pHeadarr[i])
    63. {
    64. List* pDel = pHeadarr[i];
    65. pHeadarr[i] = pHeadarr[i]->pNext;
    66. arr[j++] = pDel->id;
    67. delete pDel;
    68. pDel = NULL;
    69. }
    70. }
    71. base *= 10;
    72. }
    73. }
    74. int main()
    75. {
    76. int arr[15] = { 34,36,31,78,65,32,33,34,89,90,91,67,52,71,77 };
    77. RadixSort(arr, 15);
    78. for (int val : arr)
    79. {
    80. cout << val << " ";
    81. }
    82. return 0;
    83. }

  • 相关阅读:
    数字图像处理实验记录四(图像的空间域增强-平滑处理)
    公司oa是什么?一般公司oa有什么样功能?
    Qt源码阅读(一) 信号槽的连接与调用
    Response对象-响应字符数据
    单点登录等功能该用 Keycloak 这种开源框架实现吗?
    sigmoid和softmax函数的区别;神经网路常用的损失函数以及对应的应用场景;softmax的作用
    327.区间和的个数
    【Lilishop商城】No2-6.确定软件架构搭建五(本篇包括定时任务xxl-job)
    【和小白一起练习CTF】攻防世界:web基础练习题(2)
    关于#r语言#的问题:有没有随机多属性可接受性分析(SMAA)的R语言代码
  • 原文地址:https://blog.csdn.net/van9527/article/details/126232966