資料結構 JAVA描述(十二) 歸併排序 鏈式基數排序
阿新 • • 發佈:2019-02-17
歸併排序
/**
* @description 2-路歸併排序演算法 歸併過程中引入陣列temp[],第一趟由a歸併到temp,第二趟由temp歸併到a,如此反覆直到n個記錄為一個有序表
* 返回的是a[]。不論是偶數趟還是奇數趟,最後都會mergepas(temp, a, s, n); 資料都會在a中
* @return
* @author liuquan
* @date 2016年1月5日
*/
public static int[] mergeSort(int[] before){
int [] a= Arrays.copyOf(before, before.length);
int s = 1; //s為已排序的子序列長度
int n = a.length;
int[] temp = new int[n];
while(s < n){
mergepas(a, temp, s, n);
s *= 2;
mergepas(temp, a, s, n);
s *= 2;
}
return a;
}
/**
* @description 一趟歸併排序的演算法
* @param a
* @param b
* @param s s是待歸併的有序子序列的長度
* @param n n是待排序序列的長度
* @author liuquan
* @date 2016年1月5日
*/
private static void mergepas(int[] a, int[] b, int s, int n){
int p = 0; //p為每一對待合併表的第一個元素的下標
//首先兩兩歸併長度均為s的有序表
while(p + 2 * s - 1 <= n - 1){
merge(a, b, p, p + s - 1, p + 2 * s -1);
p += 2 * s;
}
//歸併最後兩個長度不相等的有序表
if(p * s - 1 < n - 1){
merge(a, b, p, p + s - 1, n - 1);
}
else{ //只剩餘一個有序表了,直接複製到b中
for(int i = p; i <= n - 1; i++){
b[i] = a[a];
}
}
}
/**
* @description 把兩個相鄰的有序表a[h……m]和a[m+1……t]歸併成一個有序表 b[h……t]
* @author liuquan
* @date 2016年1月5日
*/
private static void merge(int[] a, int[] b, int h, int m, int t){
int i = h, j = m +1, k = h;
//將a中兩個相鄰子序列歸併到b中
while(i <= m && j <= t){
if(a[i] <= a[j]){
b[k++] = a[i++];
}
else{
b[k++] = a[j++];
}
}
//將剩餘子序列複製到b中
while(i <= m){
b[k++] = a[i++];
}
while(j <= t){
b[k++] = a[j++];
}
}
空間複雜度:O(n),存在一個輔助陣列
時間複雜度:歸併趟數為[㏒₂ n],而每一對有序序列的歸併時的比較次數均不大於記錄的移動次數,而記錄的移動次數=n,所以時間複雜度是O(n ㏒₂ n)
演算法穩定性:穩定
基數排序
假設n個記錄的排序表中的每個記錄包含d個關鍵字{k1,k2,……kd},排序的有序表是指表中任意兩個記錄a[i]和a[j]都滿足有序關係:
(ki1,ki2,ki3……kid) < (kj1,kj2……kjd)
其中k1稱為最主位關鍵字,kd稱為最次位關鍵字
多關鍵字的排序有兩種:
最主位優先(Most Significant Digit First),簡稱MSD法
最次位優先(Least Significant Digit First),簡稱LSD法
在基數排序中,常使用d表示關鍵字的位數,用rd表示關鍵字可取值的種類數,例如:關鍵字為一個3位數,則d = 3,每一個關鍵字為數字,rd=10.
執行基數排序可採用連結串列的儲存結構,用一個長度為n的單鏈表r存放待排序的n個記錄,再使用兩個長度為rd的一維陣列f和e,分別存放rd個佇列中指向隊首結點和隊尾結點的指標:
- 形成初始連結串列
- 將最小的關鍵字值作為當前關鍵字,即i=d
- 執行第i趟分配和收集。鏈頭和鏈尾分別由f[0……rd-1]和e[0……rd-1]指向,再將這rd個子序列頭尾相連形成一個新的當前處理序列。
- 將當前關鍵字向高位推進一位,即i = i-1;重複執行上面步驟,直到d位關鍵字處理完畢。
空間複雜度: 2*rd個隊首和隊尾的輔助空間,n個連結串列指標
時間複雜度:O(d(n+rd))
其中一趟分配的時間複雜度為0(n),一趟收集的時間複雜度為O(rd),共進行了d趟分配和收集,所以時間複雜度是O(d(n+rd))演算法穩定性:穩定