參考文章: 前言
計數排序、基數排序和桶排序三種排序演算法由於都不是基於比較的排序
,因此這三種排序演算法可以以線性時間執行
。但是因為限制條件的特殊性,因此應用面沒有基於元素比較的排序演算法廣,但是在很多特定的情況下還是蠻有用途的,而且效率極高。
計數排序
計數排序是建立在這樣的前提條件下的:假設n
個輸入元素的每乙個都是0到k區間內的乙個整數,其中k
為某個整數。因此我們後面所寫的程式也只是針對0
到k
之間的元素進行排序,換句話說,排序元素中不能有負數。
計數排序的基本思想是:對乙個輸入元素x
,先確定所有輸入元素中小於x
的元素個數,那麼排序後x
所在的位置也就明確了。比如,所有的輸入元素中有10
個元素小於x
,那麼排好序後x的位置序號就應該是11
。當然,如果有相同元素,自然要放到相鄰的位置上。
演算法導論上給出了計數排序的很詳細的偽**,我們根據此偽**,並設陣列arr
為輸入陣列,arr
中的每個元素值在0到k
之間,brr
為排序後的輸出陣列,crr
記錄arr
中每個元素出現的次數。寫出**如下:
//計數排序1:使用額外陣列brr來儲存排序結果
/* * 計數排序的順序是從小到大
* arr[0...len-1]為排序陣列,每個元素均是0~k中的乙個數
* brr[0...len-1]為排序後的輸出陣列
* crr[0...k]儲存arr陣列中每個值出現的次數
*/public
void
countsort1(int arr,int brr,int crr,int len,int k)
//遍歷arr陣列,把arr中的元素放在brr中對應的位置上
for(i = len-1;i>=0;i--)
}
很明顯上面**的時間複雜度為o(n+k)
,但用到了brr來儲存排序結果,我們可以它做些改進,使排序原地進行,如下:
//計數排序2:就地排序,不使用額外陣列
/* 第二種形式實現計數排序
計數排序後的順序為從小到大
arr[0...len-1]為待排陣列,每個元素均是0-k中的乙個值
crr[0...k]儲存0...k中每個值在陣列arr中出現的次數
*/public
void
countsort2(int arr,int crr,int len,int k) }}
採用如下**測試:
@test
public
void
test() ;
int len = arr.length;
int brr = new
int[9];
int k = 10;
int crr = new
int[k+1];
//countsort1(arr,brr,crr,len,k);
countsort2(arr,crr,len,k);
system.out.println(arrays.tostring(arr));
}
測試結果如下:
最後我們稍微總結下計數排序的特點:
1、不是基於比較的排序,因此可以達到線性排序時間;
2、採取空間換時間的思想,需要brr和crr
等輔助空間,但是時間複雜度僅為o(n+k)
;
3、穩定性好,這也是計數排序最重要的乙個特性。
在實際工作中,當k=o(n)
時,我們一般才會採取計數排序,如果k很大,則不宜採取該演算法,尤其在如下情形下:
待排序元素為:1、3、8、5、10000000
,這樣會造成很大的資源浪費。
演算法系列8 計數排序
計數排序 counting sort 字典計數 還原 計數排序的核心在於將輸入的資料值轉化為鍵儲存在額外開闢的陣列空間中。作為一種線性時間複雜度的排序,計數排序要求輸入的資料必須是有確定範圍的整數 計數排序是一種穩定的排序演算法。計數排序使用乙個額外的陣列c,其中第i個元素是待排序陣列a中值等於i的...
演算法 排序 計數排序
計數排序不是基於比較的排序演算法,其核心在於將輸入的資料值轉化為鍵儲存在額外開闢的陣列空間中。作為一種線性時間複雜度的排序,計數排序要求輸入的資料必須是有確定範圍的整數。計數排序 counting sort 是一種穩定的排序演算法。計數排序使用乙個額外的陣列c,其中第i個元素是待排序陣列a中值等於i...
演算法 排序 計數排序
計數排序的核心思想就是將需要排序的陣列的元素轉為下標,在輔助空間陣列 輔助空間陣列的初始都是0 中找到對應元素的下標位置,將該位置的元素 掃瞄下標,將對應不為0的下標記錄賦值給原陣列,然後對應下標元素 圖例分析 具體 includevoid countsort int a,int len int m...