排序演算法(計數排序,基數排序,桶排序)
1. 計數排序
思想:對於有限個一定範圍內的整數,我們可以採用遍歷的方式得出每一個數的個數,放入相應的值所對應的下標陣列的位置中,再通過將原陣列從後往前遍歷,並對照與 計數陣列之間的關係,將原陣列資料排好序放入新的陣列中。一般情況下k<=len,程式碼如下:
void CountSort(int arr[],int ret[],int k,int len ) //k代表原陣列中不重複的數的個數,即將相同數值的數記為1,有多少個不同的數
{
int *c=(int *)malloc(sizeof(int)*(k)); //申請空間以計數
memset(c,0,sizeof(int)*(k)); //將計數陣列每一個元素初值初始化為0
for(int i=1,i<=len;++i) //迴圈遍歷原陣列,遍歷完成之後,陣列c中存放的各個數值對應的個數,如c[5]=2表示原陣列中5的個數有2個
{
c[arr[i]]++;
}
for(i=2;i<=k;++i)
{
c[i]+=c[i-1]; //陣列c記錄小於等於原陣列值的個數有幾個
}
for(int j=len;j>0;j--)
{
ret[c[arr[j]]]=arr[j]; //最終ret陣列中c[arr[j]]的位置就存放原陣列中的該值
c[arr[j]]--; //一個數已經排好序,則相應計數位置應少1
}
}
計數排序的最大時間複雜度為O(k+n),並且為穩定排序。
2.基數排序
思想:基數排序主要針對一個數的位數進行排序,如各個待排序數的個位,十位,百位進行排序,先對個位進行排序,再依據個位排序,對十位進行排序,進行區域性位置調整,調整完成之後再依據相對有序的當前排序數進行百位排序,假設每個數最多隻有三位的話,通過百位排序並進行調整之後,就有序了。程式碼如下:
RADIX-SORT( A , d ) 1 for i← 1 to d 2 douse a stable sort to sort array A on digiti |
int brr[len]={0};
void RadisSort(int arr[],int ret[],int len,int d)//d表示最大的數的位數有幾位
{
for(int i=1,i<=d;++i)
{
for(int j=1;j<=len;++j)
{
brr[j]=arr[j]/pow(10,i-1)%10; //取得各位數值的相應的個位,十位百位等的數值
}
CountSort(arr,brr,ret[],k,len ); //呼叫穩定的計數排序進行當前位置的數值排序,這裡不能完全套用上面的計數排序,但思路相同。
arr=ret;
}
}
3.桶排序
思想:桶排序將均勻分佈的隨機的固定區間的小數等份劃分之後,通過將這些小數經過雜湊函式雜湊到各個桶中,則前一個桶中的資料肯定小於後一個桶中的資料,對於桶的個數,我們想劃分為幾個區間,就是幾個桶,也即陣列的長度,對於桶中的資料,我們可以採用連結串列的形式將其資料有序插入到相應桶中,這裡的連結串列是針對單個桶內的元素而言,因為我們並不知道一個桶中到底會有多少元素。虛擬碼描述如下: