马士兵老师的算法课
4.基数排序
算法思想:
- 多关键字排序,按个位十位百位依次排序
- 分配一个0到9的桶count数组,从个位排起,对个位取余,按0到9放进对应编号的桶里;
- 对桶的序号进行累加运算,得到桶里最后一个值的下标,然后从后往前遍历原数组arr,把arr[n]赋值给result[count[num]-1],count[num]–;
- 然后排十位…循环最高位次
每次count数组都要归零,一共循环原数组中最大数的位数(如数组里最大是三位数,就循环三次),需要定义一个函数寻找最高位。
时间复杂度:O(n*k),k代表了几位数
空间复杂度:O(n)
寻找最大值的位数:
int maxlength(vector<int>& arr) //计算最大值的长度
{
int d = 1;
int p = 10;
for (int i = 0; i < arr.size(); i++)
{
while (arr[i] >= p)
{
p *= 10;
++d;
}
}
return d;
}
radix算法:
vector<int> radix(vector<int>& arr)
{
int d = maxlength(arr);
vector<int> result(arr.size()); //定义一个结果数组
vector<int> count(int(10)); //定义一个count数组,即桶
for (int i = 0; i < d; i++)
{
int division = (int)pow(10, i); //个十百位
for (int j = 0; j < arr.size(); j++) //对个、十、百...位进行取余,放进对应的桶中
{
int num = (arr[j] / division) % 10;
count[num]++;
}
for (int m = 1; m < count.size(); m++) //计算每个桶里的最后一个元素的下标
{
count[m] = count[m] + count[m - 1];
}
for (int n = arr.size() - 1; n >= 0; n--) //把arr从后往前遍历,放进result数组中
{
int num = (arr[n] / division) % 10;
result[count[num]-1] = arr[n];
count[num]--;
}
for (int k = 0; k < arr.size(); k++) //把result结果传给arr,预备下一次排序
{
arr[k] = result[k];
}
for (int a = 0; a < 10; a++) //循环一次后,将桶归零
{
count[a] = 0;
}
}
return result;
}
总结:
1.本质上是一种多关键字排序
2.有低位优先和高位优先两种