基本排序算法Java實現歸納(二)

1. 選擇排序

1.1 簡單選擇排序

簡單選擇排序的思想是:在數組r[1…n]中,第一趟從r[1]開始,進行n-1次比較,找出關鍵字最小的記錄,與r[1]進行交換,第二趟從r[2]開始,進行n-2次比較,在剩餘記錄中找出關鍵字最小的記錄,以此類推,經過n-1趟,排序完成。該排序方法主要通過多次遍歷數組,每次遍歷數組時將所遍歷到的最小數據與未排序數據最左端交換,最終使得數組正序。以下是簡單選擇排序的java實現:

    /**
     * 
     * 直接選擇排序
     * 時間複雜度O(n²)
     * 空間複雜度O(1)
     * 可用於鏈式存儲結構
     * 不穩定排序
     * 移動記錄次數較少
     * 每一記錄佔用的空間較多時優於直接插入排序
     * 
     */
    private static void directSelectionSort(int[] array) {
        for (int i = 0; i < array.length; i++) {
            int k = i;
            for (int j = i+1; j < array.length; j++) {
                if(array[j] < array[k]) {
                    k = j;
                }
            }
            if(k!=i) {
                int tmp = array[i];
                array[i] = array[k];
                array[k] = tmp;
            }
        }
        printArray(array);
    }

1.2 簡單選擇排序

堆排序算法的主要思想就是,將無需序列建成初堆以後,反覆將堆的根結點與堆的最後一個結點交換,然後再將除最後一個結點的樹重新調整爲堆,經過多次調整後,由於堆的性質(堆是一種經過排序的完全二叉樹,其中任一非終端節點的數據值均不大於(或不小於)其左孩子和右孩子節點的值。根結點(亦稱爲堆頂)的關鍵字是堆裏所有結點關鍵字中最小者的堆稱爲小根堆。 根結點(亦稱爲堆頂)的關鍵字是堆裏所有結點關鍵字中最大者,稱爲大根堆。)最後該堆能夠變成有序狀態。堆排序經歷三個主要過程:
1)建初堆
從i=n/2(即最後一個有子節點的節點)開始,將i減小,反覆使用篩選法,依次將以r[i]爲根的子樹調整爲堆,通過對每一個子樹變爲堆達到整棵樹變成堆的目的。
2)調整堆
調整堆的過程作用於該結點以及該結點的所有子孫結點。沿着key較大的孩子結點向下篩選,將每一個結點及其所有子孫節點通過兩兩比較進行交換的方式調整爲堆。
3)堆排序
堆排序的過程是將前面兩個過程進行整合,先進行建初堆,然後通過循環將堆的根結點與未排序的最後一個結點進行交換,然後再從樹的根部開始,對整顆未排序的樹進行堆調整,如此循環,最後使得堆達到有序。以下是堆排序的java實現:

    /**
     * 
     * 堆排序
     * 時間複雜度O(nlong2n)
     * 空間複雜度O(1)
     * 只能用於順序結構
     * 不穩定排序
     * 記錄多時爲高效
     * 
     */
    private static void heapSort(int[] array) {
        CreateHeap(array);
        for (int i = array.length-1; i > 0; i--) {
            int tmp = array[0];
            array[0] = array[i];
            array[i] = tmp;
            HeapAdjust(array, 0, i-1);
        }
        printArray(array);
    }

    //調整成大根堆
    private static void HeapAdjust(int[] array, int s, int m) {
        int root = array[s];
        for (int i = 2*s+1; i <= m; i= 2*i+1) {
            if(i<m&&array[i]<array[i+1])
                i++;
            if(root>=array[i])
                break;
            array[s] = array[i];
            s = i;
        }
        array[s] = root;
    }

    //把array建成大根堆
    private static void CreateHeap(int[] array) {
        int n = array.length - 1;
        for (int i = n/2; i >= 0; i--) {
            HeapAdjust(array, i, n);
        }
    }

2. 歸併排序

歸併排序的算法思想是:將當前通過遞歸方法循環地一分爲二,直至序列被分爲若干個只含一條數據的表,然後再將相鄰表兩兩合併。合併方法爲:每次分別從兩個表中取出一個記錄進行關鍵字的比較,將較小着放入T中,重複此過程,直至其中一個表爲空,最後將另一非空表中餘下的部分直接複製到T中。即兩個相鄰表的數據存放在同一個數組中的不同初始下標內,每次合併的時候將這兩個相鄰表合併後,重新組合其在數組中的位置。以下是歸併排序的java實現:

    /**
     * 
     * 歸併排序
     * 時間複雜度O(nlong2n)
     * 空間複雜度O(n)
     * 可用於鏈式結構
     * 穩定排序
     * 
     */ 
    private static void mergeSort(int[] array) {
        Msort(array, array, 0, array.length-1); 
        printArray(array);
    }

    private static void Msort(int[] R, int[] T, int low, int high) {
        int[] S = new int[R.length];
        if(low == high)
            T[low] = R[low];
        else {
            int mid = (low + high) / 2;
            Msort(R, S, low, mid);
            Msort(R, S, mid+1, high);
            Merge(S, T, low, mid, high);
        }
    }

    private static void Merge(int[] R, int[] T, int low, int mid, int high) {
        int i = low;
        int j = mid + 1;
        int k = low;
        while (i<=mid&&j<=high) {
            if(R[i]<=R[j])
                T[k++] = R[i++];
            else
                T[k++] = R[j++];
        }
        while (i<=mid)
            T[k++] = R[i++];
        while (j<=high)
            T[k++] = R[j++];
    }

3. 基本排序算法java實現彙總

public class Sort {

    public static void main(String[] args) {

        int[] array = {49, 38, 65, 97, 76, 13, 27, 49};

        /**
         * InsertSort
         */
//      directInsertSort(array);
//      binaryInsertSort(array);
//      ShellSort(array);


        /**
         * ExchangeSort
         */
        bubbleSort(array);
//      quickSort(array);


        /**
         * SelectSort
         */
//      directSelectionSort(array);
//      heapSort(array);


        /**
         * MergeSort
         */
//      mergeSort(array);

    }


    /**
     * 
     * 歸併排序
     * 時間複雜度O(nlong2n)
     * 空間複雜度O(n)
     * 可用於鏈式結構
     * 穩定排序
     * 
     */ 
    private static void mergeSort(int[] array) {
        Msort(array, array, 0, array.length-1); 
        printArray(array);
    }

    private static void Msort(int[] R, int[] T, int low, int high) {
        int[] S = new int[R.length];
        if(low == high)
            T[low] = R[low];
        else {
            int mid = (low + high) / 2;
            Msort(R, S, low, mid);
            Msort(R, S, mid+1, high);
            Merge(S, T, low, mid, high);
        }
    }

    private static void Merge(int[] R, int[] T, int low, int mid, int high) {
        int i = low;
        int j = mid + 1;
        int k = low;
        while (i<=mid&&j<=high) {
            if(R[i]<=R[j])
                T[k++] = R[i++];
            else
                T[k++] = R[j++];
        }
        while (i<=mid)
            T[k++] = R[i++];
        while (j<=high)
            T[k++] = R[j++];
    }


    /**
     * 
     * 堆排序
     * 時間複雜度O(nlong2n)
     * 空間複雜度O(1)
     * 只能用於順序結構
     * 不穩定排序
     * 記錄多時爲高效
     * 
     */
    private static void heapSort(int[] array) {
        CreateHeap(array);
        for (int i = array.length-1; i > 0; i--) {
            int tmp = array[0];
            array[0] = array[i];
            array[i] = tmp;
            HeapAdjust(array, 0, i-1);
        }
        printArray(array);
    }

    //調整成大根堆
    private static void HeapAdjust(int[] array, int s, int m) {
        int root = array[s];
        for (int i = 2*s+1; i <= m; i= 2*i+1) {
            if(i<m&&array[i]<array[i+1])
                i++;
            if(root>=array[i])
                break;
            array[s] = array[i];
            s = i;
        }
        array[s] = root;
    }

    //把array建成大根堆
    private static void CreateHeap(int[] array) {
        int n = array.length - 1;
        for (int i = n/2; i >= 0; i--) {
            HeapAdjust(array, i, n);
        }
    }


    /**
     * 
     * 直接選擇排序
     * 時間複雜度O(n²)
     * 空間複雜度O(1)
     * 可用於鏈式存儲結構
     * 不穩定排序
     * 移動記錄次數較少
     * 每一記錄佔用的空間較多時優於直接插入排序
     * 
     */
    private static void directSelectionSort(int[] array) {
        for (int i = 0; i < array.length; i++) {
            int k = i;
            for (int j = i+1; j < array.length; j++) {
                if(array[j] < array[k]) {
                    k = j;
                }
            }
            if(k!=i) {
                int tmp = array[i];
                array[i] = array[k];
                array[k] = tmp;
            }
        }
        printArray(array);
    }


    /**
     * 
     * 快速排序
     * 時間複雜度O(nlog2n)
     * 空間複雜度最好O(log2n)最差O(n)
     * 需要定位表的上界和下界適合順序結構
     * 不穩定排序
     * 平均情況是所有內部排序方法中速度最快的一種
     * 
     */
    private static void quickSort(int[] array) {
        qSort(array, 0, array.length-1);
        printArray(array);
    }

    private static void qSort(int[] array, int low, int high) {
        if(low < high) {
            int index = Partition(array, low, high);
            qSort(array, low, index-1);
            qSort(array, index+1, high);
        }
    }

    private static int Partition(int[] array, int low, int high) {
        int tmp = array[low];
        while (low < high) {
            while (low<high && array[high]>=tmp) {
                high--;
            }
            array[low] = array[high];   

            while (low<high && array[low]<=tmp) {
                low++;
            }
            array[high] = array[low];
        }
        array[low] = tmp;
        return low;
    }


    /**
     * 
     * 冒泡排序
     * 時間複雜度O(n²)
     * 空間複雜度O(1)
     * 可用於鏈式存儲結構
     * 穩定排序
     * 平均時間性能比直接插入排序差
     * 
     */
    private static void bubbleSort(int[] array) {
        int flag = 1;
        for (int i = array.length - 1; i > 0 && flag == 1; i--) {
            flag = 0;
            for (int j = 0; j < i; j++) {
                if(array[j] > array[j+1]) {
                    flag = 1;
                    int tmp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = tmp;
                }
            }
        }
        printArray(array);
    }


    /**
     * 
     * 希爾排序
     * 時間複雜度O(n的1.3次方)
     * 空間複雜度O(1)
     * 記錄跳躍式移動導致不穩定排序
     * 適合初始記錄無序、n較大的情況
     * 
     */
    private static void ShellSort(int[] array) {
        //定義增量數組
        int dt[] = {5, 3, 1};
        for (int i = 0; i < dt.length; i++) {
            ShellInsert(array, dt[i]);
        }
        printArray(array);
    }

    private static void ShellInsert(int[] array, int t) {
        for (int i = t; i < array.length; i++) {
            if(array[i] < array[i-t]) {
                int tmp = array[i];
                int j;

                for (j = i-t; (j>=0)&&(tmp < array[j]); j -= t) {
                    array[j+t] = array[j];
                }

                array[j+t] = tmp;
            }
        }
    }


    /**
     * 
     * 折半插入排序
     * 時間複雜度O(n²)
     * 空間複雜度O(1)
     * 穩定排序
     * 適合初始記錄無序、n較大的情況
     * 
     */
    private static void binaryInsertSort(int[] array) {
        for (int i = 1; i < array.length; i++) {
            int temp = array[i];
            int low = 0;
            int high = array.length-1;

            while (low <= high) {
                int m = (low + high) / 2;
                if(temp < array[m]) {
                    high = m - 1;
                }
                else {
                    low = m + 1;
                }
            }

        int j;
        for (j = i-1; j >= high+1;) {
            array[j+1] = array[j];
            j--;
            if (j<0) {
                break;
            }
        }
        array[j+1] = temp;

        }

        printArray(array);
    }


    /**
     * 
     * 直接插入排序
     * 時間複雜度O(n²)
     * 空間複雜度O(1)
     * 穩定排序
     * 適合基本有序情況
     * 
     */
    private static void directInsertSort(int[] array) {
        for (int i = 1; i < array.length; i++) {
            if(array[i] < array[i-1]) {
                int temp = array[i];
                int j;
                for (j = i-1; (j>=0)&&(temp < array[j]); j--) {
                    array[j+1] = array[j];
                }

                array[j+1] = temp;
            }
        }
        printArray(array);
    }

    private static void printArray(int[] array) {
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i] + " ");
        }
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章