标签:
基数排序是箱排序的改进和推广。
1、基数排序的基本思想
箱排序也称为桶排序(Bucket Sort),其基本思想是:设置若干箱子,依次扫描待排序的记录R[0],R[1],R[2]...R[n],把关键字等于k的记录全部装入到第k个箱子里(分配),然后按序号一次将各非空的箱子收尾连接起来(收集)。
例如,要将一副混洗的52张扑克牌按点数A<2<...<J<Q<K排序,需设置13个"箱子",排序时一次将每张牌按点数放入相应的箱子里,然后依次将这些箱子首尾相连,就得到按点数递增顺序排序的一副牌。
基数排序是基于多关键字的,什么是多关键字的呢?如果文件中任何一个记录R[i]的关键字都由d个分量构成,而且这d个分量中每个分量都是一个独立的关键字,则文件是多关键字的(比如扑克牌的两个关键字:点数和花色)。
通常实现多关键字的排序有两种方法:
最高位优先和最低位优先。
基数排序是典型的LSD排序方法,其基本思想是:从低位到高位依次对数据进行箱排序。在d趟箱排序中,所需的箱子书就是基数rd(可能的取值个数),这就是"基数排序"名称的由来。
2、思想
它是一种非比较排序。它是根据位的高低进行排序的,也就是先按个位排序,然后依据十位排序……以此类推。示例如下:
3、算法复杂度
分配需要O(n),收集为O(r),其中r为分配后链表的个数,以r=10为例,则有0~9这样10个链表来将原来的序列分类。而d,也就是位数(如最大的数是1234,位数是4,则d=4),即"分配-收集"的趟数。因此时间复杂度为O(d*(n+r))。
4、稳定性
基数排序过程中不改变元素的相对位置,因此是稳定的!
5、代码实现
//使用基数排序对整数进行排序 //基数排序是复杂排序,适用于知道范围数据例如1-1000进行排序 //1.首先定义一个10个大小的指针数组,每个指针表示一个箱子,指针用于操作每个箱子 //2.在定义一个10个大小的数组,数组每个位置用于存储每个箱子装有多少元素 //3.找出数组中最大整数,得到最大整数的位数(每次除以10,记数++,直到number等于0为止) //4.为指针数组中的指针开辟内存空间,并初始化为0 //5.以最小位数开始遍历,每次遍历之前清空记数数组(count) //6.内层循环遍历数组a[0]-a[length-1],每次取得数组中元素第i位的数字xx,将元素放入数组xx中的第count[xx]位置,同时记数数组相应的数据++ //7.把所有数据存放到temp中之后,需按同位大小取出元素,根据count记数中每个记录的个数取出temp中所有元素. //8.index=0,是从原始数组的a[0]开始,若记数为0的话,直接跳过取下一个箱子的元素(最内层循环体为a[index++]=temp[j][k],取出箱子每个元素放入a数组中) //循环5-8步骤,直至最大值的最大位数循环完毕。 #include<iostream> using namespace std; //查找长度为length的数组的最大元素 int find_max(int a[], int length) { int max = a[0]; //max从a[0]开始 for (int i = 1; i < length; i++) { if (max<a[i]) //如果发现元素比max大,就重新给max赋值 { max = a[i]; } } return max; } //计算number有多少位 static int digit_number(int number) { int digit = 0; do { number /= 10; //除以10,记数+1 digit++; } while (number!=0); //直到等于0为止 return digit; } //返回number上地Kth位的数字 static int kth_digit(int a, int i) { int num = a/pow(10, i); //除以10的几次方,取余 return num%10; } //对长度为length的数组进行基数排序 static void radix_sort(int a[], int length) { int* temp[10]; //指针数组,每一个指针表示一个箱子 int i, j, k; int count[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; //用于存储每个箱子装有多少元素 int max = find_max(a, length); //取得数组中的最大整数 int digitNum = digit_number(max); //得到最大整数的位数 for (i = 0; i < 10; i++) { temp[i] = new int[length]; //是每一个箱子能装下length个int元素 memset(temp[i], 0, sizeof(int)*length); <span style="white-space:pre"> </span>//初始化为0 } for (i = 0; i < digitNum; i++) //循环几位数次 { memset(count, 0, sizeof(int)* 10); //每次装箱前把count记数数组清空 for (j = 0; j < length; j++) { int xx = kth_digit(a[j], i); //取得每位数 temp[xx][count[xx]] = a[j]; //将位数放入到对应的暂存数组中 count[xx]++; //此对应的箱子记数递增 } int index = 0; for (j = 0; j < 10; j++) //取出所有箱子中的元素,将数据从暂存数组中取回 { for (k = 0; k < count[j]; k++) <span style="white-space:pre"> </span>//把箱子里所有的 元素都去回到原始数组中 { a[index++] = temp[j][k]; } } } } static void print_array(int a[], int length) { for (int i = 0; i < length; i++) //打印数组 { cout << a[i] << " "; } } void main9mianshiti8() { int a[] = { 22, 32, 19, 53, 47, 29 }; cout << "before print_array: "; print_array(a, 6); radix_sort(a, 6); //基数排序 cout << "\nafter print_array: "; print_array(a, 6); system("pause"); }6、测试结果
before print_array:22 32 19 53 47 29
after print_array:19 22 29 32 47 53
标签:
原文地址:http://blog.csdn.net/j8121/article/details/51923866