基数排序
基数排序是一种非比较形的排序算法,是一种稳定排序算法,其原理是将整数按位数(从个位、十位、百位顺序)切割成不同的数字,分别按照位数上的值将元素放到不同的“桶子”中,如果数字当前位数上没有值,则补0。
直到最高位切割完成,则数据排序完成。
1,23,90,324,567,876,26,78,83,45,67,57,33
如上需要排序的数组最大位数为 百位,则需要先从 个位、然后十位、最后百位,分三次排序
首先按照个位上的数值,
将 1,23,90,324,567,876,26,78,83,45,67,57,33
顺序将每个数放入对应的格子内
个位 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|---|
个位 | 90 | 1 | 23 | 324 | 45 | 876 | 567 | 78 | ||
个位 | 83 | 26 | 67 | |||||||
个位 | 33 | 57 |
不需要排序,从左到右顺次将每一列的数值拿出来
90,1,23,83,33,324,45, 876,26,567,67,57, 78
然后按照十位上的数值,
将 90,1,23,83,33,324,45, 876,26,567,67,57, 78
顺序将每个数放入对应的格子内
如果某一位上没有说数值,则补0,比如 1 的十位是 0, 则将1 填到 十位为0 的列
十位 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|---|
十位 | 1 | 23 | 33 | 45 | 57 | 567 | 876 | 83 | 90 | |
十位 | 324 | 67 | 78 | |||||||
十位 | 26 |
不需要排序,从左到右顺次将每一列的数值拿出来
1,23,324,26,33,45,57,567,67,876,78,83,90
然后按照百位上的数值,顺序将每个数放入对应的格子内
如果某一位上没有说数值,则补0,比如 1 的百位是 0, 则将1 填到 百位为0 的列
百位 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|---|
百位 | 1 | 324 | 567 | 876 | ||||||
百位 | 23 | |||||||||
百位 | 26 | |||||||||
百位 | 33 | |||||||||
百位 | 45 | |||||||||
百位 | 57 | |||||||||
百位 | 67 | |||||||||
百位 | 78 | |||||||||
百位 | 83 | |||||||||
百位 | 90 |
不需要排序,从左到右顺次将每一列的数值拿出来
1,23,26,33,45,57,67,78,83,90,324,567,876
到此数组已经排好序了,中间没有经过任何比较
代码如下
void Start()
{
int[] arr = new int[] { 543, 159, 343, 287, 694, 315, 873, 96};
RadixSort(arr);
}
public void RadixSort(int[] arr)
{
int maxBit = 1;
int value = 10;
// 获取数组中最大元素位数
for (int i = 0; i < arr.Length; ++i)
{
while(arr[i] >= value)
{
value *= 10;
++maxBit;
}
}
int digit = 1;
int[] tempArr = new int[arr.Length];
while (maxBit > 0)
{
maxBit--;
// 用来技术的数组,记录 digit(个、十、百)位上每一位个数
// 比如总计五个数字:23、53、 63、73、 55、65
// 当 digit 表示个位时:
// 个位 是 3 的记作 countArr[3] = 4 包含 (23、53、 63、73 四个数字)
// 个位 是 5 的记作 countArr[5] = 2 包含 (55、65 两个数字)
// 当 digit 表示十位时:
// 十位是 2 的记作 countArr[2] = 1 包含 (23 一个数字)
// 十位是 5 的记作 countArr[5] = 2 包含 (53、55 两个数字)
// 十位是 6 的记作 countArr[6] = 2 包含 (63、65 两个数字)
// 十位是 7 的记作 countArr[7] = 1 包含 (73 一个数字)
int[] countArr = new int[10];
// 逻辑一
for (int i = 0; i < arr.Length; ++i)
{
// arr[i] 的 digit位(1 个位、10 十位、100 百位)上的值
// 以此值作为 countArr 的索引,索引数+1
int index = arr[i] / digit % 10;
countArr[index]++;
}
// 逻辑二
for (int i = 1; i < countArr.Length; ++i)
{
// 计算每个索引上的数据存放的最大位置下标
// 以上面 digit 表示十位时 为例
// 十位是 2 的有 1 个, 在数组中存取位置是 第 0 下标
// 十位是 5 的有 2 个,在数组中存取位置是 第 1 - 2 下标
// 十位是 6 的有 2 个,在数组中存取位置是 第 3 - 4 下标
// 十位是 7 的有 1 个,在数组中存取位置是 第 5 下标
countArr[i] += countArr[i - 1];
}
for (int i = arr.Length - 1; i >= 0; --i)
{
int number = arr[i] / digit % 10;
int index = countArr[number] - 1;
tempArr[index ] = arr[i];
countArr[number ]--;
}
// 将临时数据拷贝回 arr
for (int i = 0; i < tempArr.Length; ++i)
{
arr[i] = tempArr[i];
}
digit *= 10;
}
}
逻辑讲解
逻辑一 部分
for (int i = 0; i < arr.Length; ++i)
{
// arr[i] 的 digit位(1 个位、10 十位、100 百位)上的值
// 以此值作为 countArr 的索引,索引数+1
int index = arr[i] / digit % 10;
countArr[index]++;
}
按照每一位上的数值,统计该位置上的个数
1, 23, 90, 324, 567, 876, 26, 78, 83, 45, 67, 57, 33
以个位数为例:
index = 23 % 10 = 3
countArr[index]++;
就是记录 个位为 3 的添加一个
最终
countArr[0] = 1 :个位为0 的数有 1 个, 90
countArr[1] = 1 :个位为1 的数有 1 个, 1
countArr[2] = 0 :个位为2 的数有 0 个,
countArr[3] = 3 :个位为3 的数有 3 个, 23,83,33
countArr[4] = 1 :个位为4 的数有 1 个, 324,
countArr[5] = 1 :个位为5 的数有 1 个, 45,
countArr[6] = 2 :个位为6 的数有 2 个, 876, 26
countArr[7] = 3 :个位为7 的数有 3 个, 567,67,57
countArr[8] = 1 :个位为8 的数有 1 个, 78
countArr[9] = 0 :个位为9 的数有 0 个,
逻辑二 部分
for (int i = 1; i < countArr.Length; ++i)
{
// 计算每个索引上的数据存放的最大位置下标
countArr[i] += countArr[i - 1];
}
先说第一轮排序后的结果
90,1,23,83,33,324,45,876, 26, 567,67,57,78
最终
countArr[0] = 1 :个位为0 的数有 1 个,90, 最后一个,个位包含 0 的 90 应该排在第 (1 - 1) = 0 个位置
countArr[1] = 2 :个位为1 的数有 1 个, 1, 最后一个,个位包含 1 的 1 应该排在第 (2 - 1) = 1 个位置
countArr[2] = 2 :个位为2 的数有 0 个, 最后一个,个位包含 2 的应该排在第 (2 - 1) = 2 个位置,其实没有个位包含 2 的
解释一下:
个位为 0 的 90,占了 1 个位置
个位为 1 的 1,占了 1 个位置
个位为 3 的 23,83,33,占了 3 个位置,1 + 1 + 3 = 5,所以最后一个,个位包含 3 的 33 应该排在第 (5 - 1)= 4 个位置
countArr[3] = 5 :个位为3 的数有 3 个, 23,83,33, 最后一个,个位包含 3 的 33 应该排在第 (5 - 1)= 4 个位置
countArr[4] = 6 :个位为4 的数有 1 个, 324, 最后一个,个位包含 4 的 324 应该排在第 (6 - 1)= 5 个位置
countArr[5] = 7 :个位为5 的数有 1 个, 45, 最后一个,个位包含 5 的 45 应该排在第 (7 - 1)= 6 个位置
countArr[6] = 9 :个位为6 的数有 2 个, 876, 26 最后一个,个位包含 6 的 26 应该排在第 (9 - 1)= 8 个位置
countArr[7] = 12 :个位为7 的数有 3 个, 567,67,57 最后一个,个位包含 7 的 57 应该排在第 (12 - 1)= 11 个位置
countArr[8] = 13 :个位为8 的数有 1 个, 78 最后一个,个位包含 8 的 78 应该排在第 (13 - 1)= 12 个位置
countArr[9] = 13 :个位为9 的数有 0 个, 最后一个,个位包含 9 的应该排在第 (13 - 1)= 12 个位置,其实没有个位包含 9 的