演算法導論學習之二:插入排序

趙明威發表於2014-09-14

由於演算法的細節和嚴肅的,在此不詳細的談論,有興趣的同學請看演算法導論.

2.1 插入排序

有一個已經有序的資料序列,要求在這個已經排好的資料序列中插入一個數,但要求插入後此資料序列仍然有序,這個時候就要用到一種新的排序方法——插入排序法,插入排序的基本操作就是將一個資料插入到已經排好序的有序資料中,從而得到一個新的、個數加一的有序資料,演算法適用於少量資料的排序,時間複雜度為O(n^2)。是穩定的排序方法。

插入演算法把要排序的陣列分成兩部分:

第一部分包含了這個陣列的所有元素,但將最後一個元素除外(讓陣列多一個空間才有插入的位置)

第二部分就只包含這一個元素(即待插入元素)。在第一部分排序完成後,再將這個最後元素插入到已排好序的第一部分中。

插入排序的基本思想是:每步將一個待排序的紀錄,按其關鍵碼值的大小插入前面已經排序的檔案中適當位置上,直到全部插入完為止。

對於少量的排序,它是有效的演算法。insertion-sort

陣列A[1..n] 長度為A.length

    package class2;
    public class Insertion_sort {
        public static void main(String[] args) {
            int[] A = new int[]{2,4,1,5,7,1,9,7,6,8};
            long time1 = System.nanoTime();
            for (int j = 1; j < A.length; j++) {
                int key = A[j];
                int i=j-1;
                while((i>=0)&&(A[i]>key)){
                    A[i+1]=A[i];
                    i=i-1;
                    A[i+1]=key;
                }
            }
            long time2 = System.nanoTime();
            System.out.println(Arrays.toString(A));
            System.out.println(time2-time1+" ns");
    }
    [1, 1, 2, 4, 5, 6, 7, 7, 8, 9]
    6842 ns

迴圈不變式:

性質:

初始化:迴圈的第一次迭代之前,它為真。

保持:如果迴圈的某次迭代之前它為真,那麼下次迭代之前它仍為真。

終止:在迴圈終止時,不變式為我們提供一個有用的性質,該性質有助於證明演算法是正確的。 ===============================================================|

2.2分析演算法

2014年07月15日 星期二 10時37分05秒

排序演算法的分析:

    輸入規模:輸入中的項數。
    執行時間:指執行的基本運算元或步數。
    an+b:它是n的線性函式。 最好的情況
    an^2+bn+c:它是n的二次函式 最壞的情況
    平均情況:概率分析技術:隨機化演算法:期望
    執行時間的增長率或增長量級。

2.3設計演算法

    分治法:許多有用的演算法在結構上是遞迴的。
    分治模式在每層遞迴時都有三個步驟:
    1、分解:分解原問題為若干子問題,這些子問題是原問題的規模較小的例項。
    2、解決:這些子問題,遞迴地求解各子問題,遞迴求解各子問題,
                                然而,若子問題的規模足夠小,則直接求解。
    3、合併:這些子問題的解成新問題的解。

分治演算法演示:

    package class2;
    import java.util.Arrays;
    public class DivideMerge_2 {
        public static void main(String[] args) {
            int[] A = new int[]{1,2,2,5,7,1,2,3,6,8};
            Merge(A,3,5,9);
            System.out.println(Arrays.toString(A));
        }
        public static void Merge(int[] A,int p,int q,int r){
            int n1=q-p+1;
            int n2=r-q;
            int[] L = new int[n1];
            int[] R = new int[n2];
            for (int i = 0; i < n1; i++) {
                L[i]=A[p+i-1];
            }
            for (int j = 0; j < n2; j++) {
                R[j]=A[q+j];
            }
            System.out.println(Arrays.toString(L));
            System.out.println(Arrays.toString(R));    //檢視中間過程
            int a=0,b=0;
            for (int k = p-1; k < r; k++) {
                if (a<n1&&b<n2) {
                    if (L[a]<=R[b]) {
                        A[k]=L[a];
                        a=a+1;                        //哨兵
                    }else if(L[a]>R[b]){
                        A[k]=R[b];
                        b=b+1;                        //哨兵
                    }
                }else if(a>=n1&&b<=n2){
                    A[k]=R[b];
                    b=b+1;
                }else {
                    A[k]=L[a];
                    a=a+1;
                }
            }
        }
    }
    Result:
    [2, 5, 7]
    [1, 2, 3, 6]
    [1, 2, 1, 2, 2, 3, 5, 6, 7, 8]
    -----------------------------------------------------------------------------------------

歸併排序演算法:

在上面的程式碼中加入遞迴的演算法:

enter image description here

    package class2;

    import java.util.Arrays;

    public class DivideMerge3 {
        public static void main(String[] args) {
            int[] A = new int[]{2,4,1,5,7,1,9,7,6,8};
            Merge_sort(A, 1, 10);
            System.out.println(Arrays.toString(A));
        }
        public static void Merge(int[] A,int p,int q,int r){
            int n1=q-p+1;
            int n2=r-q;
            int[] L = new int[n1];
            int[] R = new int[n2];
            for (int i = 0; i < n1; i++) {
                L[i]=A[p+i-1];
            }
            for (int j = 0; j < n2; j++) {
                R[j]=A[q+j];
            }
            System.out.println(Arrays.toString(L));
            System.out.println(Arrays.toString(R));
            int a=0,b=0;
            for (int k = p-1; k < r; k++) {
                if (a<n1&&b<n2) {
                    if (L[a]<=R[b]) {
                        A[k]=L[a];
                        a=a+1;
                    }else if(L[a]>R[b]){
                        A[k]=R[b];
                        b=b+1;
                    }
                }else if(a>=n1&&b<=n2){
                    A[k]=R[b];
                    b=b+1;
                }else if(b>=n2&&a<=n1){
                    A[k]=L[a];
                    a=a+1;
                }
            }
        }
        public static void Merge_sort(int[] A,int p,int r){
            int q=0;
            if (p<r){ 
                q=(p+r)/2;
                Merge_sort(A, p, q);
                Merge_sort(A, q+1, r);
                Merge(A, p, q, r);
            }//
        }
    }
    Result:
    [2]
    [4]
    [2, 4]
    [1]
    [5]
    [7]
    [1, 2, 4]
    [5, 7]
    [1]
    [9]
    [1, 9]
    [7]
    [6]
    [8]
    [1, 7, 9]
    [6, 8]
    [1, 2, 4, 5, 7]
    [1, 6, 7, 8, 9]
    [1, 1, 2, 4, 5, 6, 7, 7, 8, 9]
    2320963  ns
    時間複雜度:nlgn

相關文章