基数排序
桶排序(Bucket Sort)
在说基数排序之前,先讲一下通排序。
Bucket Sort原理:
如果输入M个数字,这些数字介于0-N(N > 0)之间,在数据输入的时候我们预留了一个大小为数组 Count,称之为桶。
- 在输入A的时候对Count[A]进行计数,比如说在这个M个数字中输入了2次25,那么Count[25] = 2。
- 遍历Count数组,根据Count[i]的大小输出数字,比如说 Count[1] = 3,那么就输入 1,1,1,如果Count[1] = 0的时候就不输出,整个输出结果就是我们需要的有序数据。
- 由于所有数据都需要在桶中占有一个位置(无论存在不存在,不存在该位置计数为0),所以如果我们排序的数字非常大的话,那么需要一个非常大的桶。比如说我们排序的数字最大900000,那么我们就需要一个int[900000]的数组,将会极大的占用内存空间。1234567891011121314151617181920212223242526272829303132333435363738394041//Bucket Sortvoid bucketSort(int *numbers, int length, int max){int i;int buckets[max + 1];for(i = 0; i < max + 1; i++)buckets[i] = 0;for(i = 0;i < length; i++){buckets[numbers[i]]++;}int index = 0;for(i = 0;i < max + 1; i++){int j;for(j = 0; j < buckets[i]; j++){numbers[index] = i;index++;}}}//打印数组int printArray(int *array, int length){int i;for(i = 0; i < length; i++)printf("%d ", array[i]);printf("\n");}int main(){int a[] = {9,1,4,4,8,2,7,10,30,1,19,35,23};int length = sizeof(a)/sizeof(int);bucketSort(a,length, 35);printArray(a, length);return 0;}
基数排序(Radix Sort)
考虑到Bucket Sort对于内存空间消耗太大,于是我们基于该算法衍生出一种比较优化的算法,即基数排序
- 基数排序(Radix Sort)属于分配式排序,又称”桶子法”(Bucket Sort或Bin Sort),将要排序的元素分配到某些”桶”中,以达到排序的作用,基数排序的效率有时候高于其它比较性排序.
- 基数排序的方式可以采用LSD(Least sgnificant digital)或MSD(Most sgnificant digital),LSD的排序方式由键值的最右边开始,而MSD则相反,由键值的最左边开始。LSD的基数排序适用于位数小的数列,如果位数多的话,使用MSD的效率会比较好,MSD的方式恰与LSD相反,是由高位数为基底开始进行分配,其他的演算方式则都相同。
- 时间复杂度 O(P(N+B)),其中 P是排序趟数,N是要排序的元素个数,B是桶数,一趟分配时间为O(N),一趟收集为O(B),共进行P趟。
- 空间复杂度,O(NB) 其中N是要排序的个数,B是桶数
以LSD为,对[209,1,34,4,8,772,7,293,10,30,1,390,19,635,23]进行排序,以10为基数,分为10个桶。
- 第一躺
分配
0:10 30 390
1:1 1
2:772
3:293 23
4:34 4
5:635
6:
7:7
8:8
9:209 19
收集
10 30 390 1 1 772 293 23 34 4 635 7 8 209 19
- 第二趟
- 入桶
0:1 1 4 7 8 209
1:10 19
2:23
3:30 34 635
4:
5:
6:
7:772
8:
9:390 293
出桶
1 1 4 7 8 209 10 19 23 30 34 635 772 390 293
- 第三趟
- 入桶
0:1 1 4 7 8 10 19 23 30 34
1:
2:209 293
3:390
4:
5:
6:635
7:772
8:
9:
出桶
1 1 4 7 8 10 19 23 30 34 293 390 635 772
排序完毕
代码实现