1. 程式人生 > >資料結構 JAVA描述(十二) 歸併排序 鏈式基數排序

資料結構 JAVA描述(十二) 歸併排序 鏈式基數排序

歸併排序

    /**
     * @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))

  • 演算法穩定性:穩定