c++排序part3:箱子排序、基数排序、排序比较
来源:互联网 发布:网络监控价格 编辑:程序博客网 时间:2024/05/17 04:23
7.箱子排序
说明一点,箱排序实用价值不大,在此仅适用于作为基数排序的一个中间步骤,所以有必要介绍一下。
我们先来看一个场景需求:
数据库中存储了学生的姓名年龄和成绩,要求将学生按照成绩排序。如果是前面的几种简单排序,所需要花费的时间均为N方,所以介绍一种更快的排序算法:箱子排序。
简单点说,箱子排序就是把待排序元素分成几类,然后设置若干个箱子,依次扫描待排序的记录,把关键字等于k的记录全都装入到第k个箱子里(分配),然后按序号依次将各非空的箱子首尾连接起来(收集)。
对于实现箱子排序,需要能够:
1.从欲排序链表的首部开始,逐个删除每个节点,并把删除的节点放入合适的箱子中。
2.收集并链接每个箱子里的节点,产生一个排序的链表。
如果输入的链表是Chain类型,那么可以:
1.连续的删除链表的首元素,并将其插入到相应箱子链表首部。
2.逐个删除每个箱子中的元素(从最后一个箱子开始)并将其插入到一个初始为空的链表首部。
下面来总结一下箱子排序:原理:将元素分装到各个有序的箱子中,并且将箱子按照顺序生成新的序列。
要点:先分类,再排序
8.基数排序:
基数排序可以说是对上面箱子排序的扩充。箱子排序存在一个非常大的问题:如果箱子跨度range为次方级,那么箱子排序的箱子数目将会非常多。为了解决这个弊端,我们将箱子排序进行扩充。
基数排序的原理是不直接对元素进行排序,而是先将其分解,然后对每一部分进行排序。
比如对十进制三位数排序。123拆解为1,2,3;456拆解为4,5,6。先比较个位数,排好序后再比较十位数,最后再比较百位数排序,这样便可以得到最后的排序结果。
简而言之就是每次按照每个数字的一位进行排序,先按照最个位,再按照十位,依次类推至最高位。其中每一位的排序必须是稳定排序才能保证算法的正确性。
基数排序的源码:
- #include
- using
namespace std; -
- template
<</span>class T> - void
show(T intarr, n){ -
for(int i =0;i -
cout<<arr[i]<<","; -
} -
cout<<arr[n-1]<<endl; - }
-
-
- int
RadixCountSort( int*npIndex, intnMax, int*npData, intnLen){ -
//这里就不用说了,计数的排序。不过这里为了是排序稳定 -
//在标准的方法上做了小修改。 -
int* pnCount int*)malloc(sizeof(int)*= ( nMax); //保存计数的个数 -
int i = 0; -
for (i = 0; i < nMax; ++i){ -
pnCount[i] = 0; -
} -
for (i //初始化计数个数= 0; i < nLen; ++i){ -
++pnCount[npIndex[i]]; -
} -
-
for (i //确定不大于该位置的个数。= 1; i < 10; ++i){ -
pnCount[i] += pnCount[i - 1]; -
} -
-
int * int*)malloc(sizeof(int)pnSort = ( * //存放零时的排序结果。nLen); -
//注意:这里i是从nLen-1到0的顺序排序的,是为了使排序稳定。 -
for (i = nLen - 1; i >= 0; --i){ -
--pnCount[npIndex[i]]; -
pnSort[pnCount[npIndex[i]]] = npData[i]; -
} -
for (i //把排序结构输入到返回的数据中。= 0; i < nLen; ++i){ -
npData[i] = pnSort[i]; -
} -
free(pnSort); //记得释放资源。 -
free(pnCount); -
return 1; - }
-
- //基数排序
- int
RadixSort( int*nPData, intnLen){ -
//申请存放基数的空间 -
int* nDataRadix=( int*)malloc(sizeof(int)* nLen); -
int nRadixBase //初始化倍数基数为1= 1; -
int nIsOk //设置完成排序为0= 0; -
-
//循环,知道排序完成 -
while (!nIsOk){ -
nIsOk = 1; -
nRadixBase *= 10; -
int i = 0; -
for (i = 0; i < nLen; ++i){ -
nDataRadix[i] = nPData[i] % nRadixBase; -
nDataRadix[i] /= nRadixBase / 10; -
if (nDataRadix[i] > 0){ -
nIsOk = 0; -
} -
show(nPData,nLen); -
} -
if (nIsOk){ //如果所有的基数都为0,认为排序完成,就是已经判断到最高位了。 -
break; -
} -
RadixCountSort(nDataRadix, 10, nPData, nLen); -
-
} -
free(nDataRadix); -
return 1; - }
-
-
- void
main() - {
-
int inputNumber[]={212,127,425,159,681,914,326,153,558}; -
int count = 9; -
cout<<"原始数组:"<<endl; -
show(inputNumber,count); -
cout<<"排序过程:"<<endl; -
RadixSort(inputNumber,count); -
cout<<"排序结果:"<<endl; -
show(inputNumber,count); - }
基数排序的过程:
下面来分析一下基数排序的复杂度:
时间效率:设待排序列为n个记录,d个关键码,关键码的取值范围为radix,则进行链式基数排序的时间复杂度为O(d(n+radix))。
其中,一趟分配时间复杂度为O(n),一趟收集时间复杂度为O(radix),共进行d趟分配和收集。
接下来是稳定性的讨论:
基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序,最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。基数排序基于分别排序,分别收集,所以其是稳定的排序算法。
原理:将数字按位数划分出n个关键字,每次针对一个关键字进行排序,然后针对排序后的序列进行下一个关键字的排序,循环至所有关键字都使用过则排序完成。
要点:对关键字的选取,元素分配收集。
下面对前面讨论过的和未讨论的各种排序算法进行一下总结(注释:以下表格引用自明哥的博客):
时间复杂度
原理
稳定性
举例(3,1,4,5,2)
名次排序
O(n2)
稳定
名次是(3,1,4,5,2)
排序是(1,2,3,4,5)
冒泡排序
O(n2)
稳定
一次冒泡:1,3,4,2,5
二次冒泡:1,3,2,4,5
三次冒泡:1,2,3,4,5
四次冒泡:1,2,3,4,5
五次冒泡:1,2,3,4,5
插入排序
O(n2)
稳定
插入第二个:1,3,4,5,2
插入第三个:1,3,4,5,2
插入第四个:1,3,4,5,2
插入第五个:1,2,3,4,5
选择排序
O(n2)
稳定
第一次:3,1,4,2,5
第二次:3,1,2,4,5
第三次:1,2,3,4,5
第四次:1,2,3,4,5
基数排序
O(n)
稳定
一次:1,2,3,4,5
堆排序
O(nlogn)
不稳定
删除5,4,3,2,1
依次放入12345
拓扑排序
O(n2)
稳定
无
快速排序
平均O(nlog2n)
最坏O(n2)
稳定
第一次;1,3,4,5,2
第二次:1,3,4,2,5
第三次:1,2,3,4,5
归并排序
平均O(nlog2n)
最坏O(nlog2n)
稳定
3,1
1,3
1, 2, 3 ,4, 5
- c++排序part3:箱子排序、基数排序、排序比较
- [C++]数据结构:排序算法Part2----快速排序、归并排序、箱子排序、基数排序
- [C++]数据结构:排序算法Part2----快速排序、归并排序、箱子排序、基数排序
- STL练习2 实现插入排序,箱子排序和基数排序
- 排序算法 - 基数排序(C++)
- 箱子排序
- 箱子排序
- 箱子排序
- 非比较排序-----计数排序,基数排序。
- 非比较排序---计数排序&基数排序
- 非比较排序:计数排序和基数排序
- 非比较排序—计数排序&基数排序
- 基数排序----非比较型排序
- 内部非比较排序---基数排序
- 【排序】基数排序
- 【排序】基数排序
- 【排序】基数排序
- 排序 基数排序
- 理解APCS-- ARM过程调用标准
- 求等比数列的和
- c++排序part2:堆排序、快速排序、归并排序
- POJ 1064 Cable master(很好玩的二分搜索)
- 大数据之Hadoop平台(二)Centos6.5(64bit)Hadoop2.5.1伪分布式安装记录,wordcount运行测试
- c++排序part3:箱子排序、基数排序、排序比较
- 比较常用的几个正则表达式(匹配数字)
- android设置长条progressbar背景颜色
- 十大编程算法
- [目录]带你 Activiti 深度游
- android系列: LayoutInflater详解
- mtk平台改串口波特率
- 魔兽争霸war3心得体会(一):UD的冰甲蜘蛛流
- 这是一个新的开始