1. 程式人生 > >真題2017 問答題 計數排序

真題2017 問答題 計數排序

計數排序可以對0到k臨時陣列的n個整數進行排序,K為整數,排序的時間複雜度為O(n+k),它不是基於比較的演算法,時間複雜度低於任何基於比較的排序演算法。計數排序是穩定的排序。 基本思想:對每一個輸入元素x,輸入小於x的元素個數,利用這一資訊,可以直接把x放到它在輸出陣列B中的位置上。其中用來計數的陣列C的長度取決於待排序陣列A中資料的範圍(等於待排序陣列的最大值與最小值的差加上1)。 演算法的步驟如下: 1.找出待排序的陣列中最大和最小的元素 2.統計陣列中每個值為i的元素出現的次數,存入陣列C的第i項 3.對所有的計數累加(從C中的第一個元素開始,每一項和前一項相加) 4.反向填充目標陣列:將每個元素i放在新陣列的第C(i)項,每放一個元素就將C(i)減去1。 在計數排序演算法的程式碼中,假設輸入是一個初始陣列A[1…n],A.length=n, 還需要兩個陣列,臨時陣列:C[0…k]提供臨時儲存空間; 輸出陣列:B[1…n]存放排序的輸出, 《演算法導論》中給出了計數排序的演算法虛擬碼:

在這裡插入程式碼片
COUNT—SORT(A,B,k)
let C[0..k] be a new array
for i=0 to k
C[i]=0
for j=1 to A.length
C[A[j]]=C[A[j]]+1     //步驟2
for i=1 to k              //步驟3
C[i]=C[i]+C[i-1]      
for j=A.length downto 1   //步驟4
B[C[A[j]]]=A[j]       //A[j]為第j個元素對應的票數,存放在C[j]上。陣列B順序輸出
C[A[j]]=C[A[j]]-1     //C[j]每輸出一個長度就減1


計數排序的程式碼為(陣列待排序的數字在0到99之間):
1.#include<iostream>
2.usingnamespacestd;
3.#include<stdlib.h>
4.intmain()
5.{
	6.voidfsort(inta[],intb[],intn);
	7.inta[10]={15,54,40,69,91,3,7,9,10,45};
	8.intb[100];
	9.inti;
	10.fsort(a,b,10);
	11.for(i=1;i<=10;i++)
		12.cout<<b[i]<<endl;
	13.system("pause");
	14.return0;
	15.}
16.
17.voidfsort(inta[],intb[],intn)//計數排序
18.{
	19.intc[100];
	20.inti=0;
	21.for(i=0;i<100;i++)
		22.c[i]=0;
	23.for(i=0;i<n;i++)
		24.c[a[i]]++;
	25.for(i=1;i<100;i++)
		26.c[i]+=c[i-1];//C[i]存放的是小於或者等於i的元素的個數
	27.for(i=n-1;i>=0;i--)
		28.{
		29.b[c[a[i]]]=a[i];//將a[i]放到b中合適的位置
		30.c[a[i]]--;
		31.}
	32.}

N個數有N!個可能的排列情況,也就是說基於比較的排序演算法的判定樹有N!個葉子結點,比較次數至少為log(N!)=O(NlogN)(斯特林公式)。 而非基於比較的排序,如計數排序,桶排序,和在此基礎上的基數排序,則可以突破O(NlogN)時間下限。