常見排序算法 java實現

插入排序

/**
 * 插入排序
 * 感覺下面的寫法和冒泡排序類似
 * 時間複雜度:
 *      最壞:O(n2)
 *      最好:O(n)
 *      平均:O(n2)
 */
package others;
public class insertSort {
    //所謂插入排序,其實就是類似於我們玩紙牌的時候的排序方法,每抽一張牌,都在前面已經排好序的牌中找一個合適的位置插入
    public static int[] sort(int[] array){
        //先判斷數組是否符合規定,也就是長度
        if (array.length == 0 || array.length < 2){
            return array;
        }else {
            //採用兩次for循環
            //i指向當前元素的位置,由於0前面沒有任何元素,因此我們從下標爲1的地方開始
            for (int i = 1; i < array.length; i++){
                //此處for循環用來查找元素i要插入的位置
                //用temp來臨時保存當前的元素值
                int temp = array[i];
                int j =i-1;
                //此處j>=0應當放在array[j]>temp的前面
                //&&具有截斷性,所以就不會導致j=-1時的array會報的錯誤了
                while(j>=0&&array[j]>temp){
                    array[j+1]=array[j];
                    j--;
                }
                array[j+1]=temp;
            }
        }
        return array;
    }
    public static void main(String[] args){
        int array[] = {10,11,4,2,23,46,33,1};
        array = insertSort.sort(array);
        for (int num : array){
            System.out.println(num);
        }

    }
}

歸併排序

/***
 *
 *  歸併排序
 *  已完成
 **/
package others;

public class mergeSort {
    //給定一個數組和對應區域的起始和終止位置
    public static void merge(int[] array,int start,int end){
        //首先先判斷起始地址是否小於終止地址,是的話執行,否則跳過,用來處理
        if (start < end){
            //獲取要處理區間的中心mid
            int mid = (start + end) / 2 ;
            //遞歸調用merge處理index左邊
            merge(array,start,mid) ;
            //遞歸調用merge處理index右邊
            merge(array,mid + 1,end) ;
            //最後調用sort方法對此區間進行排序
            sort(array,start,mid,end) ;
        }
    }
    //其實這裏纔是歸併排序的重點,
    public static void sort(int[] nums, int low, int mid, int high) {
        //創建一個和給定區間想用長度的新的int空間
        int[] temp = new int[high - low + 1];
        int i = low;// 左指針
        int j = mid + 1;// 右指針
        int k = 0;

        // 把較小的數先移到新數組中
        //此處是將兩個有序的數組合併到一個新的數組中
        //將兩個數組i和j位置處的元素進行比較,將較小的數放入到新數組中,對應的i或者j+1,直到有一方數組遍歷完
        while (i <= mid && j <= high) {
            if (nums[i] < nums[j]) {
                temp[k++] = nums[i++];
            } else {
                temp[k++] = nums[j++];
            }
        }
        //由於我們不知道哪個數組是遍歷完的那一個,所以我們對兩個數組執行同樣的操作
        //也就是把各自數組剩餘的所有元素一次性放到新數組的後方
        //由於有一方數組是已經全部遍歷的,因此下面兩個while循環只有一個會執行
        // 把左邊剩餘的數移入數組
        while (i <= mid) {
            temp[k++] = nums[i++];
        }

        // 把右邊邊剩餘的數移入數組
        while (j <= high) {
            temp[k++] = nums[j++];
        }

        // 最後把新數組中的數覆蓋nums數組
        for (int k2 = 0; k2 < temp.length; k2++) {
            nums[k2 + low] = temp[k2];
        }
    }
    public static void main(String[] args){
        int array[] = {10,11,4,2,23,46,33,1};
        int end = array.length - 1;
        mergeSort.merge(array,0,end);
        for (int num : array){
            System.out.println(num);
        }
    }
}

快速排序

package others;
//快排
public class quickSort {
    //快排
    /**
     *  快排的思想是,選擇一個元素,通常是對應區間的第一個元素,
     *  將所有比他小的元素放到他的左邊
     *  將所有比他大的元素放到他的右邊去
     * */
    public static int[] sort(int[] array,int start,int end){
        //首先先判斷數組是否符合規定
        if(array.length < 2 || array.length == 0 || start >= end){
            return array;
        }
        int min = start;
        int max = end;
        if (min == max){
            return array;
        }
        //保存臨時值,這裏的tempNum其實就是我們用來區分大數和小數的分界值,通常取第一個
        int tempNum = array[min];
        //當沒有結束時
        while (min != max){
            //先找到區間右側第一個比tempNum小的元素的位置
            while (min < max && array[max] > tempNum){
                max--;
            }if (min<max){
                quickSort.swap(array,min,max);
                //然後交換兩個的位置,這樣一來max右側都是比tempNum大的數,同時也把這個比他小的值扔到了最前面去
                ++min;
            }
            //從區間左側找到第一個比tempNum大的元素的位置,然後交換兩個的位置,這樣min左側的數都比tempNum小,同時也把這個大數扔到了後面去
            while (min < max && array[min] <= tempNum){
                min++;
            }
            if (min < max) {
                quickSort.swap(array,min,max);
                --max;
            }
            //不斷循環
        }
        if (min == max){
            array[max] = tempNum;
        }
        //遞歸調用sort對元素左側的區域來一次,對元素右邊的區域也來一次排序
        array = sort(array,start,min-1);
        array = sort(array,max + 1,end);
        return array;
    }
    //這個函數是用於交換兩個元素的位置的
    public static void swap(int []array,int i, int j){
        int temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }

    public static void main(String[] args){
        int array[] = {10,11,4,2,23,46,33,1};
        array = quickSort.sort(array,0,array.length-1);
        for (int num : array){
            System.out.println(num);
        }
    }
}

選擇排序

//選擇排序
package others;
//  每一趟從待排序的記錄中選出最小的元素,順序放在已排好序的序列最後,直到全部記錄排序完畢。
public class selectSort {
    public static int[] srot(int[] array){
        int p = 0;
        int temp = 0;
        if (array.length < 2 || array.length == 0){
            return array;
        }
        for (int i = 0;i < array.length; i++){
            temp = i;
            for(int j = i; j < array.length; j++ ){
                if (array[j] < array[temp]){
                    temp = j;
                }
            }
            if (temp != i){
                p = array[i];
                array[i] = array[temp];
                array[temp] = p;
            }
        }
        return array;
    }

    public static void main(String[] args){
        int array[] = {10,11,4,2,23,46,33,1};
        array = selectSort.srot(array);
        for (int num : array){
            System.out.println(num);
        }
    }
}

希爾排序

/**
 * 希爾排序的時間複雜度是不確定的
 * 依賴於增量序列
 * 時間複雜度在O(n1.3~n2)
 */
package others;
/**
 * 先取一個小於n的整數d1作爲第一個增量,把文件的全部記錄分成d1個組。
 * 所有距離爲dl的倍數的記錄放在同一個組中。先在各組內進行直接插入排序;
 * 然後,取第二個增量d2<d1重複上述的分組和排序,直至所取的增量dt=1(dt<dt-l<;…<d2<d1),即所有記錄放在同一組中進行直接插入排序爲止。
 * 該方法實質上是一種分組插入方法。
 * */
public class shellSort {
    public static int [] sort(int[] array){
        int temp = 0;
        int t = 0;
        if (array.length == 0 || array.length < 2){
            return array;
        }
        temp = array.length;
        while(true){
            temp = temp / 2;
            for (int i = 0;i < temp ;i++){
                for (int index = i ;index < array.length ;index = index + temp){
                    for (int j = index; j < array.length; j = j + temp){
                        if((j + temp) < array.length) {
                            if (array[j] > array[j + temp]) {
                                t = array[j];
                                array[j] = array[j + temp];
                                array[j + temp] = t;
                            }
                        }
                    }
                }
            }
            if (temp == 1)
                break;
        }
        return array;
    }
    public static void main(String[] args){
        int array[] = {10,11,4,2,23,46,33,1};
        array = shellSort.sort(array);
        for (int num : array){
            System.out.println(num);
        }

    }
}

堆排序

import java.util.Arrays;

public class HeapSort {

    //堆排序
    public static void heapSort(int[] array) {
        array = buildMaxHeap(array); //初始建堆,array[0]爲第一趟值最大的元素
        for (int i = array.length - 1; i >= 1; i--) {
            int temp = array[0];  //將堆頂元素和堆底元素交換,即得到當前最大元素正確的排序位置
            array[0] = array[i];
            array[i] = temp;
            adjustHeap(array, 0, i);  //整理,將剩餘的元素整理成大頂堆
        }
    }

    //自下而上構建大頂堆:將array看成完全二叉樹的順序存儲結構
    private static int[] buildMaxHeap(int[] array) {
        //從最後一個節點array.length-1的父節點(array.length-1-1)/2開始,直到根節點0,反覆調整堆
        for(int i=(array.length-2)/2;i>=0;i--){
            adjustHeap(array, i, array.length);
        }
        return array;

    }

    private static void adjustHeap(int[] array, int k, int length) {
        int k1=2*k+1;
        if(k1<length-1 && array[k1]<array[k1+1]){
            k1++;
        }
        if(k1>length-1||array[k]>=array[k1]){
            return;
        }else{
            int temp = array[k];  //將堆頂元素和左右子結點中較大節點交換
            array[k] = array[k1];
            array[k1] = temp;
            adjustHeap(array,k1,length);
        }
    }



    public static void main(String[] args) {
        int[] a = {87,45,78,32,17,65,53,9,122,133};
        heapSort(a);
        System.out.println(Arrays.toString(a));
    }
}

 

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