目录
桶排序(Bucket sort)是一种排序算法,它将要排序的数据分到有限数量的桶中,然后对每个桶进行单独排序,最后将所有的桶合并在一起得到排好序的数据。
简而言之,就是把待排序序列(数组)中的数据根据某种函数映射方法分配到若干个桶中,在分别对各个桶进行排序,最后依次按顺序取出桶中的数据。
本文介绍的基数排序就是函数映射的方法之一。
基数排序是一种分配式排序算法,它根据数据的每一位数字来排序,从最低位开始,依次对位数进行排序。基数排序的具体步骤如下:
需要注意的是,基数排序适用于整数或字符串等有着逻辑位数的元素排序。
基数排序对于元素的位数要求比较高,如果待排序的元素位数较大,可能会导致较高的时间和空间复杂度。
因此,基数排序在实际应用中通常用于位数较小的整数排序或者是字符串排序。
- //获取最大位数
- int _GetMaxBit(int* array, int size)
- {
- int bit = 1;
- int max = 10;
- for (int i = 0; i < size; ++i)
- {
- while (array[i] >= max)
- {
- max *= 10;
- bit++;
- }
- }
- return bit;
- }
- //创建桶数组
- int* bucket = (int*)malloc(sizeof(int) * size);
- if (bucket == NULL)
- {
- perror("malloc");
- exit(1);
- }
- memset(bucket, 0, sizeof(int) * size);
类似于计数排序的思想,将每一位出现的次数都映射到数组中。
与计数排序不同的点是,需要存入当前的值,也是实现的难点。介绍两个思路
本方法是本文推荐实现的代码。通过两个数组存储每个值在桶数组的索引位置。这样可以将数据最后都存到一个数组中,可以极大简化后序遍历的操作。
- //计数数组
- int count[10] = { 0 };
- //位置索引数组
- int index[10] = { 0 };
- // 确定对应位桶数据的个数
- for (int i = 0; i < size; ++i)
- {
- //取出某一位
- int k = (array[i] / radix) % 10;
- //对应索引位++
- count[k]++;
- }
桶数组中的第一个数下标一定是0
某一位的第一个元素就是 索引数组的前一个值 加上 计数数组对应位的值
// 确定在桶中的位置 for (int i = 1; i < 10; ++i) { index[i] = index[i - 1] + count[i - 1]; }
- #include
- #include
- #include
- #include
- #include
-
- //获取最大位数
- int _GetMaxBit(int* array, int size)
- {
- int bit = 1;
- int max = 10;
- for (int i = 0; i < size; ++i)
- {
- while (array[i] >= max)
- {
- max *= 10;
- bit++;
- }
- }
- return bit;
- }
- //基数排序-LSD
- void RadixSort_LSD(int* array, int size)
- {
- //获取最高位数
- int maxBit = _GetMaxBit(array, size);
- //创建桶数组
- int* bucket = (int*)malloc(sizeof(int) * size);
- if (bucket == NULL)
- {
- perror("malloc");
- exit(1);
- }
- memset(bucket, 0, sizeof(int) * size);
-
- //计数数组
- int count[10] = { 0 };
- //位置索引数组
- int index[10] = { 0 };
-
- int radix = 1;
- for (int bit = 1; bit <= maxBit; ++bit)
- {
- memset(count, 0, sizeof(int) * 10);
- memset(index, 0, sizeof(int) * 10);
-
- // 确定对应位桶数据的个数
- for (int i = 0; i < size; ++i)
- {
- //取出某一位
- int k = (array[i] / radix) % 10;
- //对应索引位++
- count[k]++;
- }
- // 确定在桶中的位置
- for (int i = 1; i < 10; ++i)
- {
- index[i] = index[i - 1] + count[i - 1];
- }
- // 将数据放到对应的桶中
- for (int i = 0; i < size; ++i)
- {
- //取出某一位
- int k = (array[i] / radix) % 10;
- //放入桶中
- bucket[index[k]++] = array[i];
- }
- // 将桶中排后数据拷贝回原数组
- memcpy(array, bucket, sizeof(int) * size);
-
- radix *= 10;
- }
- free(bucket);
- bucket = NULL;
- }