计数排序(CountingSort)

一. 背景知识与目的
1、进行计数排序练习。
2、计数排序说明:
计数排序只适用于整数的排序。
3、实现原理:
1)假设整数带排序数组A[1..N]从0…K中的任意整数的数组。建立计数数组C[0…K],元素初始为0
2)然后计算A[j]元素值的个数,放在计数数组中,计算方法遍历A[1…N],C[A[j]]=C[A[j]]+1。
3)由于C[0…N]标识每个位置上的元素的个数,前一个元素加当前元素即为元素i的值的位置。相同元素占用相同位置,则计数减一依次输出。
4)举例:
a)在0-5上的数组{1,3,1,2,4,0,2},C[0…5]={0,0,0,0,0,0}
b)C[A[0]]=C[A[0]]+1=1;C[A[2]]=C[A[2]]+1=2;即元素1存在两个元素。
C)计数数组为C[0…5]={1,2,2,1,1,0}
D)位置数组为C[0…5]={1,3,5,6,7,7},解释该数组,计数数组元素5对应计数为0,位置为7,依次不输出。元素4对应计数1,位置7,因此最后一个元素为4,只输出1次。依次3。元素2对应计数2,位置5,因此第4位第5位都为2…

二. 代码实现
实现代码

        //计数排序
        //计数排序只针对整数数组排序。
        void CountingSort(T testArray[], int nSize){
            LogInfo log = LogInfo();
            log.ShowState("原始数组为:");
            log.ShowArray(testArray, nSize);
            int k(0);
            //一次遍历获取最大值与最小值
            T TMax = testArray[0], TMin = testArray[0];
            for (int i = 0; i < nSize; i++){
                if (testArray[i]>TMax){
                    TMax = testArray[i];
                }
                else if (testArray[i] < TMin){
                    TMin = testArray[i];
                }
            }
            //定义数组的范围,K一般是最大值与最小值的差值,可以超过这个值。最小值默认为0
            k = TMax - TMin + 1;
            //初始化计数器
            T* Count = new int[k];
            for (int i = 0; i < k; i++)
                Count[i] = T(0);
            //计算每个计数器位置的元素个数
            for (int i = 0; i < nSize; i++){
                Count[testArray[i] - TMin] ++;
            }
            log.ShowState("计数数组为:");
            log.ShowArray(Count, k);
            //计算位置前置和
            for (int i = 1; i < k; i++)
                Count[i] = Count[i]+Count[i-1];
            log.ShowState("位置数组为:");
            log.ShowArray(Count, k);
            //定义输出数组
            T* testOut = new T[nSize];
            for (int i = nSize - 1; i >= 0; i--){
                testOut[Count[testArray[i] - TMin]-1] = testArray[i];
                Count[testArray[i] - TMin]--;
            }
            log.ShowState("最终数组为:");
            log.ShowArray(testOut, nSize);
            delete[] testOut, Count;
        }

调用代码

int main()
{
    using namespace Test;
    using namespace MyAlgorithm;
    using namespace std;

    LogInfo<int> log = LogInfo<int>();
    Sort<int> sortTest = Sort<int>();
    log.ShowState("测试计数排序");
    log.ShowLine();
    log.ShowState("测试正序数组========================");
    log.ShowLine();
    TestDataCreator<int, N_MAX> testArray = TestDataCreator<int, N_MAX>(PositiveArray);
    sortTest.CountingSort(testArray.GetArray(), testArray.GetSize());
    log.ShowState("测试降序数组========================");
    log.ShowLine();
    testArray = TestDataCreator<int, N_MAX>(NegativeArray);
    sortTest.CountingSort(testArray.GetArray(), testArray.GetSize());
    log.ShowState("测试随机数组========================");
    log.ShowLine();
    testArray = TestDataCreator<int, N_MAX>(RandomArray);
    sortTest.CountingSort(testArray.GetArray(), testArray.GetSize());
    int nWait;
    cin >> nWait;
    return 0;
}

结果输出
计数排序(CountingSort)_第1张图片
三. 遇到问题
1、需要输出计数数组与位置数组因此Count定义为T*
2、由于位置从1开始,因此放在数组中需要-1
3、无法确定K值,因此一次遍历获取最大值与最小值。
四. 经验总结
1、计数排序算法稳定。空间复杂度O(N+K),时间复杂度为O(N+K),对于本例时间复杂度为O(2*N+K)
2、计数排序不用比较元素的大小,基于位置计数。是一种线性复杂度的排序算法。
3、最坏情况下,任何比较排序复杂度都至少需要Nlog2(N)次比较。
五. 后续计划
1、进行基数排序与桶排序练习。

六. 参考文献
1、算法导论
2、 八大排序算法 http://blog.csdn.net/abcbig/article/details/42774333
3、计数排序http://www.cnblogs.com/kaituorensheng/archive/2013/02/23/2923877.html

你可能感兴趣的:(C++,Primer,Plus,Algorithm)