学习《算法导论》第八章 计数排序 总结

来源:互联网 发布:安徽航信网络发票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;}
0 0
原创粉丝点击