一、基数排序简介
基数排序是一种非比较排序算法,它将整数按照个位、十位、百位等位数进行排序。基数排序的主要思想是先按照最低位进行排序,然后依次按照高位进行排序,直到最高位,从而得到最终有序的序列。
基数排序的算法步骤如下:
- 将所有待比较数值统一为同样的位数,位数较小的数前面补零。
- 从最低位开始,依次进行一次计数排序(或桶排序),根据当前位数字进行分配。
- 重复以上步骤,直到最高位,最终得到有序序列。
基数排序的时间复杂度为O(d*(n+r)),其中d为最大位数,n为元素个数,r为基数(0-9为10进制时r为10)。
基数排序适用于位数较小、取值范围较小的整数排序,但对于位数较大的数字或负数排序则不太适用。
二、基数排序思想
基数排序是一种非比较性排序算法,其基本思想是将待排序的元素按照个位、十位、百位等基数进行排序。具体操作步骤如下:
- 将数组中的元素按照个位数字进行排序,可以使用计数排序等方法;
- 将数组按照个位数字排序后,根据十位数字再次排序;
- 以此类推,直到最高位数字排序完毕,整个数组就变成有序的了。
基数排序的时间复杂度取决于位数和元素的范围,适用于待排序元素范围不大的情况。其优点是稳定性高,不受待排序元素的大小影响,且不需要比较操作,适用于整数排序等场景。
三、代码实现
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<queue>
int Get_num_Max_digit(int arr[], int len)
{
int max = arr[0];
for (int i = 1; i < len; i++)
{
if (arr[i] > max)
{
arr[i] = max;
}
}
//定义一个计数器,用于获取数组中最大值的位数
int count = 0;
while (max != 0)
{
max /= 10;
count++;
}
return count;
}
//获取数字对应位数的值
int Get_num_corresponding_Bucket(int num, int gap)
{
for (int i = 0; i < gap; i++)
{
num /= 10;
}
return num % 10;
}
//对数组进行一次基数排序
void Radix(int arr[], int len, int gap)
{
std::queue<int> Bucket[10];//10个队列
//遍历数组,将元素分配到对应的桶
for (int i = 0; i < len; i++)
{
//Get_num_corresponding_Bucket(arr[i], gap) 的作用是:
//提取 arr[i] 的第 gap 位数字(如 gap = 1 取个位,gap = 10 取十位)。
int index = Get_num_corresponding_Bucket(arr[i], gap);
Bucket[index].push(arr[i]);
}
int k = 0;
for (int i = 0; i < 10; i++)
{
while (!Bucket[i].empty())//判断队列不空
{
arr[k++] = Bucket[i].front();//按桶顺序(0~9)收集元素,放回原数组
Bucket[i].pop();//再将元素踢出来
}
}
}
//基数排序主函数
void Radix_Sort(int arr[], int len)
{
int digit = Get_num_Max_digit(arr, len);
for (int i = 0; i < digit; i++)
{
Radix(arr, len, i);
}
}
void Show(int arr[], int len)
{
for (int i = 0; i < len; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
int main()
{
int arr[] = { 170, 45, 75, 90, 802, 24, 2, 66 };
int len = sizeof(arr) / sizeof(arr[0]);
Radix_Sort(arr, len);
Show(arr, len);
return 0;
}
四、性能分析
4.1 时间复杂度
基数排序的时间复杂度为 O(d(n + r)),其中 d是数字的位数,n 是待排序元素的数量,r 是基数,通常为 10(十进制)。在最好情况下,当待排序元素的位数较少且分布较为均匀时,基数排序的时间复杂度接近 O(n)。这是因为在每一轮对特定位数进行排序时,分配和收集操作的时间复杂度与元素数量和基数有关,而如果位数较少且分布均匀,那么总的时间复杂度就会较低。
4.2 空间复杂度
基数排序的空间复杂度为 O(n + r)。其中, n 是待排序元素的数量,r 是基数。空间复杂度主要来源于存储桶或计数数组的空间。在基数排序过程中,需要创建多个桶或计数数组来存储中间结果。例如,在十进制基数排序中,需要创建 个桶来存储不同位数的数字。每个桶的大小取决于待排序元素的数量,因此总的空间复杂度为 O(n + r)。
4.3 稳定性分析
基数排序是一种稳定的排序算法。稳定性是指在排序过程中,相等元素的相对顺序不会改变。基数排序之所以是稳定的,是因为在每一轮对特定位数进行排序时,采用的是稳定的计数排序或桶排序方法。例如,在对个位数字进行排序时,如果有多个数字的个位数字相同,那么它们在桶中的顺序与在原数组中的顺序是一致的。在后续的十位、百位等位数的排序过程中,也会保持这种相对顺序不变。