基数排序(Radix Sort)
基数排序类似于桶排序,是一种借助多关键字排序的思想对单逻辑关键字进行排序的方法。
最高位优先(Most Significant Digit first)法,简称MSD法:依次元素的高位到低位为关键字进行分桶排序。
最低位优先(Least Significant Digit first)法,简称LSD法:依次元素的低位到高位为关键字进行分桶排序。
基数排序是一种稳定的排序方式
效率分析:
时间效率:设待排序列为n个记录,d个关键码,关键码的取值范围为radix,则进行链式基数排序的时间复杂度为O(d(n+radix)),其中,一趟分配时间复杂度为O(n),一趟收集时间复杂度为O(radix),共进行d趟分配和收集。
空间效率:需要2*radix个指向队列的辅助空间,以及用于静态链表的n个指针。—百度百科
排序示例:
假设有一个序列:S[143,275,257,102,347,562,264,786,715,913]
以10为基数截取关键字,并以LSD法排序:
1. 对原数组以个位为关键字进行排序
个位序号 | 元素 | 元素 |
---|---|---|
0 | ||
1 | ||
2 | 102 | 562 |
3 | 143 | 913 |
4 | 264 | |
5 | 275 | 715 |
6 | 786 | |
7 | 257 | 347 |
8 | ||
9 |
个位排位结果为:[102,562,143,913,264,275,715,786,257,347]
- 根据个位排序的结果再以十位为关键字进行排序
十位序号 | 元素 | 元素 |
---|---|---|
0 | 102 | |
1 | 913 | 715 |
2 | ||
3 | ||
4 | 143 | 347 |
5 | 257 | |
6 | 562 | 264 |
7 | 275 | |
8 | 786 | |
9 |
十位排位结果为:[102,913,715,143,347,257,562,264,275,786]
- 根据十位排序的结果再以百位为关键字进行排序
百位序号 | 元素 | 元素 | 元素 |
---|---|---|---|
0 | |||
1 | 102 | 143 | |
2 | 257 | 264 | 275 |
3 | 347 | ||
4 | |||
5 | 562 | ||
6 | |||
7 | 715 | 786 | |
8 | |||
9 | 913 |
百位排位结果为:[102,143,257,264,275,347,562,715,786,913]
示例代码:
public static void RadixLSDSort(int[] S, int radix = 16) {
//int digit = S.Max().ToString().Length; //10进制可以用这种方式取位数
//列表中最大数按radix进位制的位数
int digit = (int)Math.Ceiling(Math.Log(S.Max(), radix));
int i = 0;
int j = 0;
List<int>[] buckets = new List<int>[radix];
for(i = 0; i < radix; i++) {
buckets[i] = new List<int>(); //初始化桶
}
for (i = 1; i <= digit; i++) {
foreach (var item in S) {
//元素入桶
buckets[item / (int)Math.Pow(radix, i - 1) % radix].Add(item);
}
j = 0;
foreach(var bucket in buckets) {
foreach(var item in bucket) {
S[j++] = item; //将桶中元素倒回原数组
}
}
for (i = 0; i < radix; i++) {
buckets[i].Clear();//清空桶
}
}
}
public static void RadixMSDSort(int[] S, int radix = 16) {
int digit = (int)Math.Ceiling(Math.Log(S.Max(), radix));
RadixMSDSort(S, S.ToList(), radix, 0, digit);
}
private static void RadixMSDSort(int[] S, List<int> sub, int radix, int start, int digit) {
if (sub.Count <= 1 || digit < 1) {
return;
}
int i;
List<int>[] bucket = new List<int>[radix];
for (i = 0; i < radix; i++) {
bucket[i] = new List<int>(); //初始化桶
}
foreach (var item in sub) {
//元素入桶
bucket[item / (int)Math.Pow(radix, digit - 1) % radix].Add(item);
}
i = start;
foreach (var data in bucket) {
foreach (var item in data) {
S[i++] = item;//将桶中元素倒回原数组
}
}
i = 0;
foreach (var data in bucket) {
//对下一位进行递归基数排序
RadixMSD2Sort(S, data, radix, start + i, digit - 1);
i += data.Count;
}
}
def radix_lsd_sort(s, radix = 16): #Python
digit = int(math.ceil(math.log(max(s), radix)))
buckets = [[] for i in range(radix)]
for i in range(1, digit+1):
for item in s:
buckets[int(item // (radix ** (i-1)) % radix)].append(item)
del s[:]
for bucket in buckets:
s.extend(bucket)
buckets = [[] for i in range(radix)]
def radix_msd_sort(s, radix = 16):
def inner_radix_msd_sort(s, sub, radix, start, digit):
if len(sub) <= 1 or digit < 1:
return
buckets = [[] for i in range(radix)]
for item in sub:
buckets[int(item // (radix ** (digit-1)) % radix)].append(item)
i = start
for bucket in buckets:
for item in bucket:
s[i] = item
i += 1
i = 0
for bucket in buckets:
inner_radix_msd_sort(s, bucket, radix, start+i, digit-1)
i += len(bucket)
digit = int(math.ceil(math.log(max(s), radix)))
inner_radix_msd_sort(s, s, radix, 0, digit)
文中若有什么错误,欢迎留言指正。
转载请保留出处:http://blog.csdn.net/x1060549/article/details/78927021