(1)原理和**以及時間複雜度分析
1.計數排序的原理:設被排序的陣列為a,排序後儲存到b,c為臨時陣列。所謂計數,首先是通過乙個陣列c[i]計算大小等於i的元素個數,此過程只需要一次迴圈遍歷就可以;在此基礎上,計算小於或者等於i的元素個數,也是一重迴圈就完成。下一步是關鍵:逆序迴圈,從length[a]到1,將a[i]放到b中第c[a[i]]個位置上。原理是:c[a[i]]表示小於等於a[i]的元素個數,正好是a[i]排序後應該在的位置。而且從length[a]到1逆序迴圈,可以保證相同元素間的相對順序不變,這也是計數排序穩定性的體現。在陣列a有附件屬性的時候,穩定性是非常重要的。
2.計數排序的前提及適用範圍:a中的元素不能大於k,而且元素要作為陣列的下標,所以元素應該為非負整數。而且如果a中有很大的元素,不能夠分配足夠大的空間。所以計數排序有很大侷限性,其主要適用於元素個數多,但是普遍不太大而且總小於k的情況,這種情況下使用計數排序可以獲得很高的效率。
3.演算法**及測試**:
#include #include #define max 1000
//函式原型
void counting_sort(int a,int length_a,int b,int k);
//測試**
int main()
;//1到10,十個測試資料
int b[11]=;
int k=10;//所有測試資料都處於0到k之間
counting_sort(a,10,b,k);
for(int i=1;i<11;i++)
printf("%d ",b[i]);
getch();
}//計數排序
void counting_sort(int a,int length_a,int b,int k)
;//c是臨時陣列
for(int i=1;i<=length_a;i++)
c[a[i]]++;
//此時c[i]包含等於i的元素個數
for(int i=1;i<=k;i++)
c[i]=c[i]+c[i-1];
//此時c[i]包含小於或者等於i的元素個數
for(int i=length_a;i>=1;i--)//從length_a到1逆序遍歷是為了保證相同元素排序後的相對順序不改變
}
4.時間複雜度分析:整個counting_sort中,只有3個單重迴圈,所以時間複雜度為o(n)。屬於非比較型別的排序,比較型別的排序的時間下界都是o(nlogn)
(2)計數排序的擴充套件
1.對負數排序的擴充套件思路:計數排序要求元素能夠作為陣列的下標,自然不能是負數。我的思路是先把負數和非負數分離開來,對負數取絕對值,再對這兩組數分別計數排序,最後再把兩組數合併可以了。時間複雜度依舊是o(n),只是n會大一點。當然處理的都是整數。
2.對浮點數排序的擴充套件思路:浮點數不能作為陣列下標。先後否定了自己兩個比較雞肋的辦法,這裡寫乙個我認為可以作為基礎的演算法,但是還需要非常大的改進。把乙個浮點數儲存在乙個鍊錶中,每個結點儲存一位,然後對每一組結點進行計數排序。這樣會導致o(n2)的時間複雜度,我還沒想到如何進行優化,如果您有思路,請告訴小弟我,非常感謝。
總結:計數排序不是就地排序,需要借助乙個輔助空間並且儲存結果到另乙個空間,而且適用範圍相對狹窄,但是卻有著o(n)的時間複雜度。我現在理解到演算法設計就是在時間和空間,以及適用範圍之間找乙個最優的平衡點。
計數排序及其擴充套件思路
計數排序的基本思想是 統計乙個數序列中小於某個元素a的個數為n,則直接把該元素a放到第n 1個位置上。當然當過有幾個元素相同時要做適當的調整,因為不能把所有的元素放到同乙個位置上。計數排序假設輸入的元素都是0到k之間的整數。1 原理和 以及時間複雜度分析 1.計數排序的原理 設被排序的陣列為a,排序...
演算法 計數排序及其變體
簡介 用於整數排序,不同於比較排序,計數排序假設輸入元素的大小在0到k之間,通過計算比 i 小的數的個數而確定 i 的位置。思路 計算所排序的陣列中,比元素 i 小的數的個數 n,如果n 5,那麼 i 就應該排列在第6個位置上,通過計算每乙個元素的 n 值,我們就能知道每乙個元素的位置,因為元素有可...
歸併排序及其擴充套件問題
歸併排序是建立在歸併操作上的一種有效的排序演算法,是採用分治法 divide and conquer 的乙個非常典型的應用。後面的擴充套件題目,小和問題和逆序對個數問題,用文字真是解釋的稀爛,自己都看不下去。還是再紙上畫一畫,debug看一下 執行的流程會比較好。演算法 如下 public clas...