計數排序

綜述

計數排序不是基于比較的排序算法,其核心在于將輸入的數據值轉化為鍵存儲在額外開辟的數組空間中.
作為一種線性時間復雜度的排序,計數排序要求輸入的數據必須是有確定范圍的整數.

算法描述

1.找出待排序的數組中最大和最小的元素;
2.統(tǒng)計數組中每個值為i的元素出現的次數,存入數組C的第i項;
3.對所有的計數累加(從C中的第一個元素開始,每一項和前一項相加);
4.反向填充目標數組:將每個元素i放在新數組的第C(i)項,每放一個元素就將C(i)減去1.

示意圖

計數排序動態(tài)示意圖
計數排序靜態(tài)示意圖

性質

排序類別:非交換排序
是否是穩(wěn)定排序:穩(wěn)定
是否是原地排序:否
時間復雜度:O(n+k)
空間復雜度:O(k)


說明

它的優(yōu)勢在于在對一定范圍內的整數排序時,它的復雜度為Ο(n+k)(其中k是整數的范圍),快于任何比較排序算法.
當然這是一種犧牲空間換取時間的做法,而且當O(k)>O(n*log(n))的時候其效率反而不如基于比較的排序
基于比較的排序的時間復雜度在理論上的下限是O(n*log(n)), 如歸并排序,堆排序

計數排序是一個穩(wěn)定的排序算法.
當輸入的元素是n個0到k之間的整數時,時間復雜度是O(n+k),空間復雜度也是O(n+k),其排序速度快于任何比較排序算法.
當k不是很大并且序列比較集中時,計數排序是一個很有效的排序算法.
計數排序的缺點是當最大值最小值差距過大時,不適用計數排序,當元素不是整數值,不適用計數排序.

算法思想

計數排序對輸入的數據有附加的限制條件:
1术辐、輸入的線性表的元素屬于有限偏序集S称鳞;
2匪燕、設輸入的線性表的長度為n,|S|=k(表示集合S中元素的總數目為k),則k=O(n).
在這兩個條件下,計數排序的復雜性為O(n).

計數排序的基本思想是對于給定的輸入序列中的每一個元素x,確定該序列中值小于x的元素的個數(此處并非比較各元素的大小,而是通過對元素值的計數和計數值的累加來確定).一旦有了這個信息,就可以將x直接存放到最終的輸出序列的正確位置上.例如,如果輸入序列中只有17個元素的值小于x的值,則x可以直接存放在輸出序列的第18個位置上.當然,如果有多個元素具有相同的值時,我們不能將這些元素放在輸出序列的同一個位置上,因此,上述方案還要作適當的修改.

算法過程

假設輸入的線性表L的長度為n,L=L1,L2,..,Ln挣输;線性表的元素屬于有限偏序集S,|S|=k且k=O(n),S={S1,S2,..Sk};則計數排序可以描述如下:
1姿搜、掃描整個集合S,對每一個Si∈S,找到在線性表L中小于等于Si的元素的個數T(Si);
2捆憎、掃描整個線性表L,對L中的每一個元素Li,將Li放在輸出線性表的第T(Li)個位置上,并將T(Li)減1.

Python實現

def count_sort1(array):
    length = len(array)
    res = [None] * length
    # 首次循環(huán)遍歷, 每個列表的數都統(tǒng)計
    for index in range(length):
        # p 表示 a[i] 大于列表其他數 的次數
        p = 0
        # q 表示 等于 a[i] 的次數
        q = 0
        # 二次循環(huán)遍歷, 列表中的每個數都和首次循環(huán)的數比較
        for two_index in range(length):
            if array[index] > array[two_index]:
                p += 1
            elif array[index] == array[two_index]:
                q += 1
        for k in range(p, p + q):  # q表示相等的次數,就表示, 從p開始索引后, 連續(xù)q次,都是同樣的數
            res[k] = array[index]
    return res

dest = [5, 2, 7, 4, 8, 1, 6, 3]
result = count_sort1(dest)
print('最后的結果是:', result)

'''
最后的結果是: [1, 2, 3, 4, 5, 6, 7, 8]
'''

C語言實現

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


void CountSort(int *arr, int len){
    if(arr == NULL) return;
    int max = arr[0], min = arr[0];
    for(int i = 1; i < len; i++){
        if(arr[i] > max)    max = arr[i];
        if(arr[i] < min)    min = arr[i];
    }
    int size = max - min + 1;
    int *count =(int*)malloc(sizeof(int)*size);
    memset(count, 0, sizeof(int)*size);

    for(int i = 0; i < len; i++)
        count[arr[i] - min]++;//包含了自己舅柜!
    for(int i = 1; i < size; i++)
        count[i] += count[i - 1];

    int* psort =(int*)malloc(sizeof(int)*len);
    memset(psort, 0, sizeof(int)*len);

    for(int i = len - 1; i >= 0; i--){
        count[arr[i] - min]--;//要先把自己減去
        psort[count[arr[i] - min]] = arr[i];
    }

    for(int i = 0; i < len; i++){
        arr[i] = psort[i];
    }

    free(count);
    free(psort);
    count = NULL;
    psort = NULL;
}


void print_array(int *arr, int len)
{
    for(int i=0; i<len; i++)
        printf("%d ", arr[i]);
    printf("\n");
}

int main()
{
    int arr[8] = {5, 2, 7, 4, 8, 1, 6, 3};
    CountSort(arr, 8);
    print_array(arr, 8);

    return 0;
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市攻礼,隨后出現的幾起案子业踢,更是在濱河造成了極大的恐慌,老刑警劉巖礁扮,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件知举,死亡現場離奇詭異,居然都是意外死亡太伊,警方通過查閱死者的電腦和手機雇锡,發(fā)現死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來僚焦,“玉大人锰提,你說我怎么就攤上這事。” “怎么了立肘?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵边坤,是天一觀的道長。 經常有香客問我谅年,道長茧痒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任融蹂,我火速辦了婚禮旺订,結果婚禮上,老公的妹妹穿的比我還像新娘超燃。我一直安慰自己区拳,他們只是感情好,可當我...
    茶點故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布意乓。 她就那樣靜靜地躺著樱调,像睡著了一般。 火紅的嫁衣襯著肌膚如雪洽瞬。 梳的紋絲不亂的頭發(fā)上本涕,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天,我揣著相機與錄音伙窃,去河邊找鬼菩颖。 笑死,一個胖子當著我的面吹牛为障,可吹牛的內容都是我干的晦闰。 我是一名探鬼主播,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼鳍怨,長吁一口氣:“原來是場噩夢啊……” “哼呻右!你這毒婦竟也來了?” 一聲冷哼從身側響起鞋喇,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤声滥,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后侦香,有當地人在樹林里發(fā)現了一具尸體落塑,經...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年罐韩,在試婚紗的時候發(fā)現自己被綠了憾赁。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,488評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡散吵,死狀恐怖龙考,靈堂內的尸體忽然破棺而出蟆肆,到底是詐尸還是另有隱情,我是刑警寧澤晦款,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布炎功,位于F島的核電站,受9級特大地震影響柬赐,放射性物質發(fā)生泄漏亡问。R本人自食惡果不足惜官紫,卻給世界環(huán)境...
    茶點故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一肛宋、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧束世,春花似錦酝陈、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至贫堰,卻和暖如春穆壕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背其屏。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工喇勋, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人偎行。 一個月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓川背,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蛤袒。 傳聞我的和親對象是個殘疾皇子熄云,可洞房花燭夜當晚...
    茶點故事閱讀 45,500評論 2 359

推薦閱讀更多精彩內容