資料結構之 線性計數排序

2021-09-25 13:58:03 字數 1922 閱讀 9438

看這篇部落格前建議先去了解桶排序

桶排序是線性排序一種,因為他的排序演算法時間複雜度是線性的,所以我們把這類演算法稱之為線性排序

首先,我們來看桶排序。桶排序,顧名思義,會用到「桶」,核心思想是將要排序的資料分到幾個有序的桶裡,每個桶裡的資料再單獨進行排序。桶內排完序之後,再把每個桶裡的資料按照順序依次取出,組成的序列就是有序的了。

桶排序時間複雜度是o(n),為什麼呢?

因為如果要排序的資料有 n 個,我們把它們均勻地劃分到 m 個桶內,每個桶裡就有 k=n/m 個元素。每個桶內部使用快速排序,時間複雜度為 o(k * logk)。m 個桶排序的時間複雜度就是 o(m * k * logk),因為 k=n/m,所以整個桶排序的時間複雜度就是 o(n*log(n/m))。當桶的個數 m 接近資料個數 n 時,log(n/m) 就是乙個非常小的常量,這個時候桶排序的時間複雜度接近 o(n)。

那麼桶排序這麼優秀,是否可以代替其他的排序演算法呢?no

首先,要排序的資料需要很容易就能劃分成 m 個桶,並且,桶與桶之間有著天然的大小順序。這樣每個桶內的資料都排序完之後,桶與桶之間的資料不需要再進行排序。

其次,資料在各個桶之間的分布是比較均勻的。如果資料經過桶的劃分之後,有些桶裡的資料非常多,有些非常少,很不平均,那桶內資料排序的時間複雜度就不是常量級了。在極端情況下,如果資料都被劃分到乙個桶裡,那就退化為 o(nlogn) 的排序演算法了。

所以就引進來今天說的基數排序,基數排序其實是桶排序一種特殊情況,當要排序的 n 個資料,所處的範圍並不大的時候,比如最大值是k,我們就可以把資料劃分成 k 個桶。每個桶內的資料值都是相同的,省掉了桶內排序的時間。

比如高考查分,我們查分數的時候,系統會顯示我們的成績以及所在省的排名。如果你所在的省有 50 萬考生,如何通過成績快速排序得出名次呢?

考生的滿分是 900 分,最小是 0 分,這個資料的範圍很小,所以我們可以分成 901 個桶,對應分數從 0 分到 900 分。根據考生的成績,我們將這 50 萬考生劃分到這 901 個桶裡。桶內的資料都是分數相同的考生,所以並不需要再進行排序。我們只需要依次掃瞄每個桶,將桶內的考生依次輸出到乙個陣列中,就實現了 50 萬考生的排序。因為只涉及掃瞄遍歷操作,所以時間複雜度是 o(n)。

可能說這些有些複雜,可以對照**,其實也不難理解:

// 計數排序,a 是陣列,n 是陣列大小。假設陣列中儲存的都是非負整數。

public void countingsort(int a, int n)

} int c = new int[max + 1]; // 申請乙個計數陣列 c,下標大小 [0,max]

for (int i = 0; i <= max; ++i)

// 計算每個元素的個數,放入 c 中

for (int i = 0; i < n; ++i)

// 依次累加

for (int i = 1; i <= max; ++i)

// 臨時陣列 r,儲存排序之後的結果

int r = new int[n];

// 計算排序的關鍵步驟,有點難理解

for (int i = n - 1; i >= 0; --i)

// 將結果拷貝給 a 陣列

for (int i = 0; i < n; ++i)

}

重在理解,計數排序只能用在資料範圍不大的場景中,如果資料範圍 k 比要排序的資料 n 大很多,就不適合用計數排序了。而且,計數排序只能給非負整數排序,如果要排序的資料是其他型別的,要將其在不改變相對大小的情況下,轉化為非負整數。

比如,如果考生成績精確到小數後一位,我們就需要將所有的分數都先乘以 10,轉化成整數,然後再放到 9010 個桶內。再比如,如果要排序的資料中有負數,資料的範圍是 [-1000, 1000],那我們就需要先對每個資料都加1000,轉化成非負整數。

資料結構 計數排序

題目來自灰灰考研 counting sort基本思想 對於給定的輸入序列中的每乙個元素x,確定該序列中值小於x的元素的個數 一旦有了這個資訊,就可以將x直接存放到最終的輸出序列的正確位置上。它建立乙個長度為這個資料範圍的陣列c,c中每個元素記錄要排序陣列中對應記錄的出現個數。下面以示例來說明這個演算...

資料結構 計數排序

計數排序基於桶排序。比如待排陣列 a 5 那麼就需要建造 105 max 100 min 1 6 大小的臨時陣列,將這 5 個元素按照,值減 100 min 作為下標儲存在臨時陣列中。如下圖所示 計數排序 param a paramn private static void jishu int a,...

資料結構 計數排序

之前講到的插入 希爾 選擇 堆 冒泡 快速 歸併排序都屬於比較排序 涉及到兩個數的比較 接下來要講到一種非比較排序演算法 計數排序。1 什麼是計數排序 計數排序是一種非比較性質的排序演算法,元素從未排序狀態變為已排序狀態的過程,是由額外空間的輔助和元素本身的值決定的。計數排序過程中不存在元素之間的比...