算法--基数排序
来源:互联网 发布:othello棋 uct算法 编辑:程序博客网 时间:2024/04/29 21:26
基数排序
基数排序是一种非比较型的排序算法。
思想:
将整数分割成不同的数字,再对每一位进行比较,先从各位开始,一次往上走,直到某一位都相等。它是在一种老式穿卡机上的算法。当然在典型的顺序随机存取计算机上,又是采用基数排序算法对多个关键字域进行排序。例如我们对生日的排序,不仅可以从年份开始,也可以从日期开始。
来源:
在老式的穿卡机中,利用卡片记录数据,每一个卡片中有多个列,每一列有12个位置,可以在任一个位置进行打卡,然后将卡片进行排序。但是我们一次只能看到卡片中的一列,当然基于原来的思想是从高位开始排序,与桶排序一样,将数据进行分割,但好似我们知道在桶排序中我们有一个存储索引的数组。在这里我们还要再添加另外的卡片进行数据的记录,显然是不合理的。这个时候只能从低位开始往高位进行排序,当高位的数字一样,依旧保持着上次的排序结果。
模拟:
假如有几个数字:329,457,657,839,436,720,355。那么排序结果为:每一列为一次运行结果
329
720
720
329
457
355
329
355
657
436
436
436
839
457
839
457
436
657
355
657
720
329
457
720
355
839
657
839
效能分析:
若给定n个d位数,每一个数位可以去k中可能的值。如果所用的稳定排序需要(n+k)的时间,那么技术排序算法能够以d(n+k)的时间正确的对这些数进行排序。为什么会有(n+k)呢,这个让我们记起比较排序,貌似都是n(lgn)的情况,是的,计数排序,因为每一位数我们都是有范围的,若是10进制的话,不过最大的是0-9的范围。对辅助数组赋初值为k,对辅助数组计算元素出现次数为n。
与快速排序的分析:
基数排序看上去似乎要比快速排序的平均情况好一些。计数排序作为中间稳定排序的基数排序不是在位的排序,而快排就可以做到。快排比基数排序更为有效利用硬件缓存。所以当内存比较珍贵的时候还是用快排。并且,在每一遍处理的时间要比快排长。另外它的隐含因子就是d(n+k)前面的数值并不确定。我们依旧不能够知道哪个效率会高一些。
代码:
struct RadixTempNode{public:int bitNum;//元素出现的次数int bitLocation;//最后这个元素所在的位置RadixTempNode(){bitNum=0;bitLocation=0;}};
template<class T>T* RadixList<T>::RadixSort(T *radixArray,int length){//思想:将所有的待比较整数统一为有相同位数长度,数位较短的前面补零。//然后从地位到高位依次进行一次排序。在每个位上可以采用效率较好的排序算法//这里我们采用的是计数排序,但是计数排序不是稳定的排序算法,于是我们要进行改进RadixTempNode tempArray[10];//每一位都是0-9,这里假设是10进制的情况T *resultArray=new T [length];//排序后的数组bool bitPos=true;int modeData=10;int bitData=0;while(bitPos)//当位数存在时,下面将利用到的是计数排序 {bitPos=false;for(int i=0;i<10;i++) { tempArray[i].bitNum=0;//赋初值为0tempArray[i].bitLocation=0; }for (int i=0;i<length;i++){*(resultArray+i)=0;//清空结果数组}for(int i=0;i<length;i++){ bitData=*(radixArray+i)%modeData/(modeData/10);//得到位数上的值if (bitData!=0){bitPos=true;}tempArray[bitData].bitNum+=1; //tempArray中索引就是余数,也就是要排序的数值, //而tempArray中的值为这个排序的数出现的次数}if (!bitPos){break;}tempArray[0].bitLocation=tempArray[0].bitNum;//加一个存储空间保证稳定算法for (int j=1;j<10;j++){tempArray[j].bitLocation=tempArray[j].bitNum+tempArray[j-1].bitLocation;//所在位置}for (int k=0;k<length;k++){ bitData=*(radixArray+k)%modeData/(modeData/10);//计数排序并不是稳定的排序算法,因此后面要改进//找到在temArray中索引为RadixArray[index]的在的数值,这个数值就是在resultArray中的位置*(resultArray+tempArray[bitData].bitLocation-tempArray[bitData].bitNum)=*(radixArray+k);tempArray[bitData].bitNum-=1;//这里必须减一否则会一直覆盖原来位置上的值,而其它的地方值却一直为0}cout<<"结果为:"<<endl;for (int i=0;i<length;i++){cout<<*(resultArray+i)<<" ";}cout<<endl;modeData*=10;//radixArray=resultArray;//若仅仅是这一条语句,没有后面的,这个时候是指针赋值,而resultArray中数据在后面中都会为0for (int index=0;index<length;index++){*(radixArray+index)=*(resultArray+index);}}return radixArray;}void RadixSortTest(){int testArray[]={329,457,657,839,436,720,355};cout<<"初始数组为:"<<endl;for(int i=0;i<7;i++){cout<<*(testArray+i)<<" ";}cout<<endl;RadixList<int>*radixSort=new RadixList<int>();int *resultArray=radixSort->RadixSort(testArray,7);cout<<"基数排序后的结果为:"<<endl;for (int i=0;i<7;i++){cout<<*(resultArray+i)<<" ";}cout<<endl;}
运行结果如上所示
小结:
1、作为非比较的排序算法,基数排序有点类似桶排序,不过一个是从高位,一个是从地位进行。
2、记得在对tempArray中赋值时与原来的计数不同,之前的计数是tempArray[indec]+=tempArray[i-1].在这里因为我们使用了一个结构体保证稳定性,所以是忽视了0位置上的值。所以tempArray[0].bitLocation=tempArray[0].bitNum;。
3、其核心代码为:*(resultArray+tempArray[bitData].bitLocation-tempArray[bitData].bitNum)=*(radixArray+ktempArray[bitData].bitNum-=1;
- 基数排序算法
- 算法-----基数排序
- 基数排序算法
- 基数排序算法
- 基数排序算法
- 基数排序算法
- 算法--基数排序
- 基数排序算法
- [算法] 基数排序
- 基数排序算法
- 基数排序算法
- 算法---基数排序
- 基数排序算法
- 基数排序算法
- 【算法】基数排序
- 基数排序算法
- 基数排序算法
- 基数排序算法
- C++primer 学习盲点(更新中)
- 中国迎来资本过剩时代
- ubuntu12下安装新浪客户端
- what is LDO
- Linux 系统下双机HA的功能实现
- 算法--基数排序
- C#语言基础理解
- 关于ld: file is universal (2 slices) but does not contain a(n) armv7s slice
- 1的数目
- spring jar 说明
- Solr1.3的启动过程分析一
- 手机研发最新资料大全
- 喝酒
- 千奇百怪问题集(不定时更新)