計數排序詳解:O(n)

計數排序基本思路爲:

  1. 我們希望能線性的時間複雜度排序,如果一個一個比較,顯然是不實際的,書上也在決策樹模型中論證了,比較排序的情況爲nlogn的複雜度。

  2. 既然不能一個一個比較,我們想到一個辦法,就是如果我在排序的時候就知道他的位置,那不就是掃描一遍,把他放入他應該的位置不就可以了嘛。

  3. 要知道他的位置,我們只需要知道有多少不大於他不就可以了嗎?

  4. 以此爲出發點,我們怎麼確定不大於他的個數呢?我們先來個約定,如果數組中的元素都比較集中,都在[0, max]範圍內。我們開一個max的空間b數組,把b數組下標對應的元素和要排序的A數組下標對應起來。這樣不就可以知道不比他大的有多少個了嗎?我們只要把比他小的位置元素個數求和,就是不比他大的。例如:A={3,5,7};我們開一個大小爲8的數組b,把a[0] = 3 放入b[3]中,使b[3] = 0; 同理 b[5] = 1; b[7] = 2;其他我們都設置爲-1,哈哈我們只需要遍歷一下b數組,如果他有數據,就來出來,鐵定是當前最小的。如果要知道比a[2]小的數字有多少個,值只需要求出b[0] – b[6]的有數據的和就可以了。這個0(n)的速度不是蓋得。

  5. 思路就是這樣咯。但是要注意兩個數相同的情況A = {1,2,3,3,4},這種情況就不可以咯,所以還是有點小技巧的。

  6. 處理小技巧:我們不把A的元素大小與B的下標一一對應,而是在B數組對應處記錄該元素大小的個數。這不久解決了嗎。哈哈。例如A = {1,2,3,3,4}我們開大小爲5的數組b;記錄數組A中元素值爲0的個數爲b[0] = 0, 記錄數組A中元素個數爲1的b[1] = 1,同理b[2] = 1, b[3] = 2, b[4] = 1;好了,這樣我們就知道比A4小的元素個數是多少了:count = b[0] + b[1] + b[2] + b[3] = 4;他就把A[4]的元素放在第4個位置。

還是截張書上的圖:
這裏寫圖片描述

源代碼:

#include <stdio.h>
#include <stdlib.h>

//計數排序
int CountSort(int* pData, int nLen)
{
    int* pCout = NULL;            //保存記數數據的指針
    pCout = (int*)malloc(sizeof(int) * nLen);    //申請空間
    //初始化記數爲0
    for (int i = 0; i < nLen; ++i)
    {
        pCout[i] = 0;
    }

    //記錄排序記數。在排序的值相應記數加1。
    for (int i = 0; i < nLen; ++i)
    {
        ++pCout[pData[i]];        //增
    }

    //確定不比該位置大的數據個數。
    for (int i = 1; i < nLen; ++i)
    {
        pCout[i] += pCout[i - 1];    //不比他大的數據個數爲他的個數加上前一個的記數。
    }

    int* pSort = NULL;            //保存排序結果的指針
    pSort = (int*)malloc(sizeof(int) * nLen);    //申請空間

    for (int i = 0; i < nLen; ++i)
    {
        //把數據放在指定位置。因爲pCout[pData[i]]的值就是不比他大數據的個數。
        //爲什麼要先減一,因爲pCout[pData[i]]保存的是不比他大數據的個數中包括了
        //他自己,我的下標是從零開始的!所以要先減一。
        --pCout[pData[i]];    //因爲有相同數據的可能,所以要把該位置數據個數減一。
        pSort[pCout[pData[i]]] = pData[i];        

    }

    //排序結束,複製到原來數組中。
    for (int i = 0; i < nLen; ++i)
    {
        pData[i] = pSort[i];
    }

    //最後要注意釋放申請的空間。
    free(pCout);
    free(pSort);

    return 1;
}

int main()
{
    int nData[10] = {8,6,3,6,5,8,3,5,1,0};
    CountSort(nData, 10);
    for (int i = 0; i < 10; ++i)
    {
        printf("%d ", nData[i]);
    }
    printf("\n");

    system("pause");
    return 0;
}
發佈了53 篇原創文章 · 獲贊 76 · 訪問量 29萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章