35.幾種常見的排序演算法

weixin_33806914發表於2019-02-13
package pandy.test.sort;

import java.util.Arrays;

/**
 * @Author: Pandy
 * @Date: 2019/2/13 20:21
 * @Version 1.0
 */
public class Sort {
    /**
     * arr.length
     * i-1 >=0
     * arr[j+1] arr[j]
     *插入排序 最好時間O(n)  平均時間O(n²)  最壞時間O(n²)  輔助空間O(1) 穩定
     * @param arr
     */
    public static void insertArray(Integer[] arr){
        int temp = 0;
        for (int i=0;i<arr.length;i++){
            for (int j = i-1;j>=0;j--){
                if (arr[j+1]>arr[j]){
                    temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                }else{
                    break;
                }
            }
        }
    }
    /**
     * 二分查詢法
     * @param arr 測試陣列
     * @param key 索引
     * @param low 陣列低位
     * @param high 陣列高位
     */
    public static int recurisionBinarySearch(int arr[],int key,int low,int high){
        if (key<arr[low]||key>arr[high]||low>high){
            return -1;
        }
        int middle = (high + low)/2;
        if (arr[middle]>key){
            return recurisionBinarySearch(arr,key,low,middle-1);
        }else if (arr[middle]<key){
            return recurisionBinarySearch(arr,key,middle+1,high);
        }else{
            return middle;
        }
    }

    /**
     * 氣泡排序
     * 前一個數字與後一個數字進行比較
     * arr.length-1
     * arr.length-1-i
     * arr[j] arr[j+1]
     *最好時間O(n) 平均時間O(n²) 最壞時間 O(n²) 輔助空間O(1) 穩定
     */
    public static void bubbleSort(int[] arr){
        int temp = 0;
        for (int i =0;i<arr.length-1;i++){
            for (int j =0;j<arr.length-1-i;j++){
                if (arr[j]>arr[j+1]){
                    temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                }
            }
        }
    }

    /**
     * 希爾排序
     *平均時間O(n 1.25次方 輔助空間O(1) 不穩定)
     * @param
     */
    public static void shellSort(int[] arr){
        int num = arr.length/3+1;
        while(num>0){
            for (int i=0;i<arr.length;i++){
                for (int j = i;j<arr.length-num;j=j+num){
                    if (arr[j]<arr[j+num]){
                        int temp = arr[j];
                        arr[j] = arr[j+num];
                        arr[j+num] = temp;
                    }
                }
            }
            num = num/2;
        }
    }

    /**
     * 快速排序
     * 最好時間O(nlgn) 平均時間O(nlgn) 最壞時間O(n²) 輔助空間O(lgn) 不穩定
     * @param
     */
    public static void fastSort(int[] arr,int low,int high){
        int start = low;
        int end = high;
        int key = arr[low];
        while(end>start){
            while(end>start&&arr[end]>=key)
                end--;
            if (arr[end]<=key){
                //交換
                int temp = arr[end];
                arr[end] = arr[start];
                arr[start] = temp;
            }
            while(end>start&&arr[start]<=key)
                start++;
            if (arr[start]>=key){
                int temp = arr[start];
                arr[start] = arr[end];
                arr[end] = temp;
            }
            if (start>low) fastSort(arr,low,start-1);
            if (end<high) fastSort(arr,end+1,high);
        }
    }

    /**
     * 選擇排序
     *最好時間O(n²) 平均時間O(n²) 最壞時間O(n²) 輔助空間O(1)
     * @param
     */
    public static void chooseSort(int[] arr){
        for (int i=0;i<arr.length-1;i++){
            int min = i;
            for (int j = i+1;j<arr.length;j++){
                if (arr[j]<arr[min]){
                    min = j;
                }
            }
            if (min != i){
                int temp = arr[min];
                arr[min] = arr[i];
                arr[i] = temp;
            }
        }
    }

    /**
     *堆排序
     * O(nlgn) 平均時間O(nlgn) 最壞時間O(nlgn) 不穩定
     * @param
     */
    public static void heapSort(int[] arr) {
        //構造大根堆
        heapInsert(arr);
        int size = arr.length;
        while(size>0) {
            //固定最大值
            swap(arr,0,size-1);
            size--;
            //構造大根堆
            heapify(arr,0,size);
        }
    }
    //構造大根堆通過新插入的數上升
    public static void heapInsert(int[] arr) {
        for(int i=0;i<arr.length;i++) {
            //當前插入的索引
            int currentIndex = i;
            //父節點的索引
            int fatherIndex = (currentIndex-1)/2;
            //如果當前插入的值大於其父節點的值
            //交換值 並將索引指向父節點
            //然後繼續和上面的父節點進行比較 直到
            //不大於父節點 則退出迴圈
            while(arr[currentIndex]>arr[fatherIndex]) {
                //交換當前節點與父節點的值
                swap(arr,currentIndex,fatherIndex);
                //將當前索引執行父索引
                currentIndex = fatherIndex;
                //重新計算當前索引的父索引
                fatherIndex = (currentIndex-1)/2;
            }
        }
    }
    //將剩餘的數構造成大頂堆
    public static void heapify(int[] arr,int index,int size) {
        int left = 2*index+1;
        int right = 2*index+2;
        while(left<size) {
            int largestIndex;
            //判斷孩子中較大值的索引 要確保右孩子在size範圍內
            if(arr[left]<arr[right]&&right<size) {
                largestIndex = right;
            }else {
                largestIndex = left;
            }
            //比較父節點中的值與孩子中較大的值 並確定最大值得索引
            if(arr[index]>arr[largestIndex]) {
                largestIndex = index;
            }
            //如果父節點索引是最大值的索引 那已經是大根堆 退出迴圈
            if(index==largestIndex) {
                break;
            }
            //父節點不是最大值 與孩子中較大的值交換
            swap(arr,largestIndex,index);
            //將索引指向孩子中較大值得索引
            index = largestIndex;
            //重新計算交換後的孩子的索引
            left = 2*index+1;
            right = 2*index+2;
        }
    }
    //交換陣列中兩個元素的值
    public static void swap(int[] arr,int i,int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    public static void main(String[] args) {
        //Integer[] arr = {45,63,23,22,54,222,78,92,32,452,12,66,595};
        int [] arr = {8,5,4,2,3,9,1,7,6};
        //Sort.insertArray(arr);
        //System.out.println(Arrays.toString(arr));
        //int result = recurisionBinarySearch(arr1,3,0,arr1.length-1)+1;
        //System.out.println(result);
        //Sort.bubbleSort(arr);
        //System.out.println(Arrays.toString(arr));
        //Sort.shellSort(arr);
        //System.out.println(Arrays.toString(arr));
        //Sort.fastSort(arr,0,arr.length-1);
        //System.out.println(Arrays.toString(arr));
        //Sort.chooseSort(arr);
        //System.out.println(Arrays.toString(arr));
        Sort.heapSort(arr);
        System.out.println(Arrays.toString(arr));
    }
}

相關文章