排序演算法之 基數排序 及其時間複雜度和空間複雜度

2021-06-29 08:11:40 字數 3881 閱讀 2900

基數排序(radix sort)屬於「分配式排序」(distribution sort),又稱「桶子法」(bucket sort)或bin sort,顧名思義,它是透過鍵值的部份資訊,將要排序的元素分配

至某些「桶」中,藉以達到排序的作用,基數排序法是屬於穩定性的排序,其時間複雜度

為o (nlog(r)m),其中r為所採取的基數,而m為堆數,在某些時候,基數排序法的效率高於其它的穩定性排序法。

基數排序的實現雖然有很多,但是基本思想就是把元素從個位排好序,然後再從十位排好序,,,,一直到元素中最大數的最高位排好序,那麼整個元素就排好序了。

比如:2,22,31,1221,90,85,105

個位排序:90,31,1221,2,22,85,105

十位排序:2,105,1221,22,31,85,90

百位排序:2,22,31,85,90,105,1221

千位排序:2,22,31,85,90,105,1221

注意:每次排序都是在上次排序的基礎上進行排序的,也就是說此次排序的位數上他們相對時,就不移動元素(即順序引數上乙個位數的排序順序)

1、把所有元素都分配到相應的桶中

2、把所有桶中的元素都集合起來放回到陣列中

3、依次迴圈上面兩步,迴圈次數為最大元素最高位數

參考下圖

1、豎  0~9:表示桶個數(每個位數上的數字都在0到9之間);

2、行 0~length:0 表示在某個桶內有多少個元素;

3、比如:所有元素中個位為5的有兩個元素,5 , 95;那麼在下圖中存放,分別是:(5,0) = 2;(5,1) = 5;(5,2)= 95;

// 列印陣列元素

void print_array(int *array, int length)

printf("\n\n"); }

// 得到陣列元素中最大數,並且計算其位數個數

void getposcount(int *array, int length, int *poscount)

*poscount = 0;

while(max)

}

void radixsort(int *array, int length)

getposcount(array, length, &poscount);// 把最高位數存放到poscount中

for (pos = 0; pos < poscount; pos++)

for (index = 0, element = 0; (element < len) && (index < length); element++)

log = log * 10;

}}

int main(void)

; //int array = ;

//int array = ;

int length = (sizeof(array)) / (sizeof(array[1]));

print_array(array, length);

radixsort(array, length);

print_array(array, length);

return 0;

}執行結果:

該演算法所花的時間基本是在把元素分配到桶裡和把元素從桶裡串起來;把元素分配到桶裡:迴圈 length 次;

把元素從桶裡串起來:這個計算有點麻煩,看似兩個迴圈,其實第二迴圈是根據桶裡面的元素而定的,可以表示為:k×buckercount;其中 k 表示某個桶中的元素個數,buckercount  則表示存放元素的桶個數;

有幾種特殊情況:

一、所有的元素都存放在乙個桶內:k = length,buckercount = 1; 第

二、所有的元素平均分配到每個桶中:k = length/ bukercount,buckercount = 10;(這裡已經固定了10個桶)

所以平均情況下收集部分所花的時間為:length (也就是元素長度 n)

綜上所述:

時間複雜度為:poscount * (length  + length) ;其中 poscount 為陣列中最大元素的最高位數;簡化下得:o( k*n ) ;其中k為常數,n為元素個數;

該演算法的空間複雜度就是在分配元素時,使用的桶空間;所以空間複雜度為:o(10 × length)= o (length)

因為基數排序是根據個位是排序好,然後再根據十位數排序好,依次類推,當最後乙個位數排序好時,所有的元素順序都排序好了。又根據計數排序的演算法可以得知,在限制元素的情況下,可以知道計數排序的時間複雜度為  o(n);所有如果利用計數排序的原理的實現基數排序,那麼時間複雜度是不是可以降低呢?

注意:如果不知道計數排序的,可以先大概了解下:

#include#includevoid print_array(int *array, int length)

printf("\n\n");

} void getcount(int *array, int length, int *count)

*count = 0;

while(max) }

void radixsort(int *array, int length)

for (i = 0; i < length; i++) array[i] = tmp[i];// 把排序好的元素放回到元素陣列中

log = log * 10;

}free(tmparray);// 釋放記憶體 }

int main(void)

; int array = ;

int length = (sizeof(array)) / (sizeof(array[1]));

print_array(array, length);

radixsort(array, length);

print_array(array, length);

return 0;

}

執行結果:

這個時間複雜度比較好計算:count * length;其中 count 為陣列元素最高位數,length為元素個數;所以時間複雜度:o( k*n )

空間複雜度是使用了兩個臨時的陣列:10 + length;所以空間複雜度:o(n)

若有不正確之處,望大家指正,共同學習!謝謝!!!

演算法 排序之基數排序

基數排序也是穩定的內排序。因為它的實現是基於內部使用了穩定的排序實現的所以基數排序整體是穩定的,而且時間複雜度為o n 舉個例子 現在我們將一些3 多 位數排序,如果你說直接判斷就好的話,那你就太天真了,因為那就又變成看o nlgn 或者o n 如何能降低時間複雜度變成o n 呢?那就要使用線性時間...

排序演算法之基數排序

首先從多排序碼排序開始介紹基數排序。以撲克牌排序為例。每張撲克牌有兩個 排序碼 花色和面值。其有序關係為 如果把所有撲克牌排成以下次序 2,a,2,a,2,a,2,a 這就是多排序碼排序。排序後形成的有序序列叫做字典有序序列。一般情況下,假定有乙個n個元素的序列 v 0,v1 vn 1 且每個元素v...

排序演算法之基數排序

如果我們要排序的資料具有多個關鍵字域,那就可以採用基數排序的方法了。基數排序的主要思想是 假如參加排序的元素最高具有d位,有的數沒有d位那麼多,則在其欠缺的高位補0,將元素先按最低位 設最右邊的位為最低位 的值進行排序,然後按次低位進行排序.最後進行最高位的排序。基數排序如果想達到理想的目的,必須滿...