非比較排序

2021-07-09 12:34:34 字數 2558 閱讀 3418

以下內容參考自《演算法導論》

基於比較的排序演算法可以用一顆完全二叉樹(決策樹)來表示,節點表示每一次的比較過程,

葉子節點表示最終的排序順序,

葉子節點一共有n!個(n表示資料個數,一共有n!種排列方式)

二叉樹的高度h就是比較的次數,由二叉樹的性質,葉子節點的個數不大於2^h,所以有

2^h>=n!;

2^h>=n! = n*(n-1)*(n-2)*...*2*1 >= n*(n-1)*(n-2)*...(n/2) > (n/2)^(n/2);

兩邊同時取對數 h > (n/2)log2(n/2);

所以 o(n) = nlog2n

堆排序和歸併排序的平均時間複雜度都是o(nlogn),所以它們是漸近最優的比較排序演算法。

那麼還有沒有更快的排序演算法呢?當然這裡的更快是針對特定資料的,排序演算法的時間複雜度下界是w(n),

因為至少每個元素都要被訪問一次,

根據hash表的思路我們可以建立乙個對映關係,建立完關係後解析得到我們想要的序列。

這種演算法以空間換時間,因此空間複雜度比較高,在某些時候未必就比基於比較的演算法更快。

計數排序就是準備和關鍵字範圍相同長度的計數陣列,先統計每個元素出現的個數,然後再求出小於等於該元素的元素個數,

也就是它應該放的地方,最後依次收集就可以了。

//計數排序

void count_sort(int a, int size)

for (i=0; i=0; i--)

for (i=0; i

int main()

; int size = sizeof(a)/sizeof(int);

count_sort(a, size);

for (int i=0; i

這裡我們舉例0-9的元素排序,準備10個桶(0-9)然後統計每個數出現的次數,要注意最後的收集是從後往前的,

因為相同的元素收集完後個數要減1,所以後面的數要先收集。

時間複雜度為o(n+k),k是n個數的範圍,範圍越大,則時間越複雜。當n和k大概相等時,複雜度可以達到o(n).

空間複雜度n+o(k),比較耗費空間。

我們可以發現,利用乙個關鍵字的計數排序面對三四位數的時候已經明顯很慢了。我們可以拆分關鍵字,按照多關鍵字排序。

就拿正整數舉例,比大小的話,高位上的數明顯比低位上的數重要。所以我們可以按多關鍵字排序。

基數排序就是這樣,但要注意我們收集的時候是先收集低位的資料排好,再收集高位的資料排列。因為先收集高位,

排低位的時候可能會把高位的數排到低位後面去,而先收集低位的話,排高位的時候只有兩種可能,高位不同或者高位相同,

如果高位相同,那麼低位已經按次序排好了,高位不同,自然不需要考慮低位,高低位都相同,由於計數排序的穩定性,

基數排序也是穩定的。

//基數排序

void radix_sort(int a, int size)

for (i=0; i=0; i--)

for (i=0; i

int main()

; int size = sizeof(a)/sizeof(int);

radix_sort(a, size);

for (int i=0; i

時間複雜度:o( d(k+n) ) ,d是關鍵字的個數,k是每乙個關鍵字的範圍;

空間複雜度:n+o(k)

桶排序其實和計數排序是一樣的,只不過《演算法導論》單獨提出來,被排序的陣列內的數值在0-1均勻分配的時候,桶排序有線性時間(θ(

n))。

其過程就是準備和高位關鍵字數量相同的桶,按高位關鍵字依次收集,高位關鍵字相同的就用陣列或鍊錶儲存值,然後再用比較排序來排序。

桶排序的平均時間複雜度分析很複雜,要用到概率論的一些知識,這裡就略過,有興趣的同學可以自己查閱《演算法導論》。

下面是使用鍊錶的桶排序:

#include #include typedef struct nodenode, *pnode;

pnode findpos(pnode head, double val)

return pre;

}void insert_sort(pnode head)

}void insertvalue(pnode head, double value)

void bucket_sort(double a, int size)

} //釋放記憶體

for (i=0; i<10; i++) }

free(bucket);

bucket = null;

}int main(void);

int size = sizeof(a)/sizeof(double);

bucket_sort(a, size);

for (int i=0; i為便於操作,使用帶頭結點的鍊錶。

桶排序的平均時間複雜度

為線性的n+o(c),其中c=n*(logn-logk)。如果相對於同樣的n,桶數量k越大,其效率越高,

最好的時間複雜度

達到o(n)。當然桶排序的空間複雜度

為n+o(k),如果輸入資料非常龐大,而桶的數量也非常多,

則空間代價無疑是昂貴的。此外,桶排序是穩定的。

非比較排序

計數排序 n個輸入元素的每乙個都是在0到k之間的整數 k為某個整數 1.假設輸入陣列是a 1.n 還需要兩個陣列 b 1.n 存放排序的輸出,c 0.k 提供臨時儲存空間 2.c i 中存放等於 i 的元素的個數,i 0,1,k 3.通過相加計算確定有多少元素是小於等於i的 4.把每個元素a i 放...

排序(二)非比較排序

七大排序那篇部落格講的排序都是比較排序,這篇部落格要寫的內容是不需要通過比較就可以排序。1.計數排序 解題思路 開闢一塊陣列,範圍為最大數減去最小數,用這個數減去最小值的差,對應的下標來統計,剛開始都初始化為0,如果有就把新開闢中的值 最後按順序遍歷新開闢的陣列,把值放到原陣列中,就可以打到排序的目...

非比較排序 計數排序

計數排序 count sort 是乙個非基於比較的排序演算法,該演算法於1954年由 harold h.seward 提出。它的優勢在於在對一定範圍內的整數排序時,它的複雜度為 n k 其中k是整數的範圍 快於任何比較排序演算法。計數排序的思想類似於雜湊表中的直接定址法,在給定的一組序列中,先找出該...