学习《算法导论》第八章 计数排序 总结
来源:互联网 发布:安徽航信网络发票2.0 编辑:程序博客网 时间:2024/06/06 23:18
学习《算法导论》第八章 计数排序 总结
前面学习的排序算法都是基于比较的. 下面学习的计数排序不是基于比较的,代码中并没出现元素之前的比较. 当我们不采用基于比较排序的模型时,排序算法的下界Ω(nlgn)在这里就不适用了. 但计数排序作了某种假设,即假设输入的元素是由一个小范围内的整数构成的.
计数排序概论
计数排序有个前提就是假设n个输入元素中的每个元素都是介于0到k之间的整数. 计数排序的运行时间是Θ(n).
计数排序的思想是:对每个输入元素x,确定出小于x的元素个数. 有了这个信息,就知道x在最后的排序数组中位于哪个位置.
计数排序的算法
这里需要两个辅助数组:
A[1…n]:待排序数组,每个元素的值都位于0到k之间.
C[0…k]: 临时数组,k为待排序数组中最大的值.
B[1…n]: 存放排序结果的数组.
COUNTING-SORT(A, B, k)1 for i to k2 do C[i] ← 03 ► C[A[j]]表示A[j]出现的次数,即等于A[j]的元素个数4 for j ← 1 to length(A)5 do C[A[j]] ← C[A[j]] + 16 ► 此时,C[i]表示小于或等于i的元素个数7 for i ← 1 to k8 do C[i] ← C[i] + C[i - 1]9 ► 下面的部分挺难理解10 for j ← length[A] downto 111 do B[C[A[j]]] ← A[j]12 C[A[j]]--
第10行到第12行比较难理解. 到第8行我们知道数组C的下标为数组A中的元素,数组C的元素值为:小于或等于数组C的下标(小于等于数组A中的该元素)的元素个数. 那么第11行就能理解了,因为若知道有10个元素比x要小,那么可以肯定x的位置为11(算法中包含了相等的情况).这里举个例子吧,如果A[3] = 8;C[A[3]] = C[8] = 6,则表示小于等于8的元素有6个. 那么A[3]这个元素在最终排序数组中的位置为6. 也就是,B[C[A[3]]] = B[C[8]] = B[6] =8.
计数排序的时间复杂度分析
由算法可知,第1-2行的for循环所用的时间为Θ(k),第3-4行的for循环所用的时间为Θ(n),第6-7行的for循环所用的时间为Θ(k),第9-11行的for循环所用的时间为Θ(n). 所以,总的时间就是Θ(k +n). 可知,计数排序的时间下界是优于Ω(nlgn).
计数排序还有一个重要的性质就是:稳定性. 即具有相同值的元素在输出数组中的相对次序与它们在输入数组中的次序是相同的.
计数排序运行过程
略(可以自己写个简单数组,模拟运行过程)
计数排序的代码实现
void CountingSort (int* InArray, int ArrayLength, int* OutArray, int ArrayNumber){ int LoopIdOne = 0; int LoopIdTwo = 0; // 申请临时数组,存放小于等于某元素的元素个数 int* ArrayTemp = (int*)malloc(sizeof(int) * ArrayNumber); if (NULL == ArrayTemp){ return;}// 初始化临时数组for (LoopIdOne = 0; LoopIdOne < ArrayNumber; LoopIdOne++){ ArrayTemp[LoopIdOne] = 0;} // 计算输入数组中包含InArray[LoopIdTwo]元素的元素个数 for (LoopIdTwo = 0; LoopIdTwo < ArrayLength; LoopIdTwo++) { ArrayTemp[InArray[LoopIdTwo]] = InArray[LoopIdTwo] + 1;}// 计算输入数组中小于等于InArray[LoopIdTwo]的元素个数for (LoopIdOne = 1; LoopIdOne < ArrayNumber; LoopIdOne++){ ArrayTemp[LoopIdOne] = ArrayTemp[LoopIdOne] + ArrayTemp[LoopIdOne - 1];}// 排序for (LoopIdTwo = ArrayLength; LoopIdTwo > 0; LoopIdTwo--){ OutArray[ArrayTemp[InArray[LoopIdTwo]]] = InArray[LoopIdTwo]; ArrayTemp[InArray[LoopIdTwo]--;}free(ArrayTemp); return;}
- 学习《算法导论》第八章 计数排序 总结
- 算法导论第八章—计数排序
- 【算法导论】第八章之计数排序
- 算法导论第八章 -- 计数排序
- 算法导论-第八章-计数排序
- 算法导论-第八章-计数排序
- 算法导论第八章(计数排序)
- 算法导论第八章计数排序-基数排序-桶排序-c++
- 算法导论 第八章计数排序(counting sort)
- 算法导论第八章__实现计数排序
- 算法导论第八章伪码转C++_计数排序
- 算法导论第八章总结:线性时间排序
- 《算法导论》学习之计数排序
- 算法导论_计数排序学习笔记
- 计数排序-《算法导论》学习笔记八
- 算法导论 学习笔记 第八章 线性时间内的排序
- 算法导论 计数排序
- 【算法导论】计数排序
- Android之测试前期那点事
- HDU 2037 今年暑假不AC(贪心)
- springmvc + freemarker 实现hello-world
- 软件测试初体验
- 华为2015机试--记录出错的代码所在的文件名称和行号
- 学习《算法导论》第八章 计数排序 总结
- HealthKit 框架体系
- [leetcode] 151.Reverse Words in a String
- linux系统中读写流程
- HDU 3501 Calculation 2(欧拉函数)
- HDOJ 1217 Arbirage(最短路)
- 基于spark1.4.1的sparkR的实例操作
- HDU 2039 三角形(水~)
- HDOJ 题目3954 Level up(线段树去见面更新区间查询)