通俗理解插入排序(直接插入排序,折半插入排序,希爾排序)

直接插入排序

直接插入排序就是將待排序的值,逐一按元素的大小插入前面的有序序列
例如對-23,45,2,-45,9,5,3,65,-24進行直接插入排序,我們可以看成將45,2,-45,9,5,3,65,-24逐步插入-23的序列
這裏寫圖片描述

package sort;
public class Demo6 {
    public static void main(String[] args) {
        int[] num = new int[]{-23,45,2,-45,9,5,3,65,-24};
        sort(num);
        for (int i = 0; i < num.length; i++) {
            System.out.print(num[i]+" ");
        }
    }
    public static void sort(int[] data){
        int tmp;//暫時保存待插入的值
        //從第2個開始,進行n-1的插入操作
        for (int i = 1; i < data.length; i++) {
            //若待插入的值比前面有序序列的最大值都大,則說明現在就是有序的
            if(data[i]<data[i-1]){
                tmp = data[i];
                int j = i-1;
                for (; j >=0&&data[j]>tmp; j--) {
                    data[j+1] = data[j];//把數據往後移動
                }
                data[j+1] = tmp;//退出循環時候,j指向的數值比tmp小,或者j<0
            }
        }
    }
}

這裏寫圖片描述

折半插入排序

折半插入排序是對直接插入排序的一種改進,直接插入排序中0到i-1有序的,折半插入排序就是用折半查找迅速找到需要插入的地方,而不用從i-1開始逐一向前比較。

這裏寫圖片描述
使用折半查找查找3應該插入的位置,
1. low=0 hight=6 mid=(low+hight)/2=3
因爲data[3]<=data[7],說明應該插入的位置在4-6之間
這裏寫圖片描述
2. low=mid+1=3+1=4 hight=6 mid=(low+hight)/2=5
這裏寫圖片描述
因爲data[5]>data[7]說明應該插入的位置在4到5間

3 low=4 hight=mid-1=5 mid=(4+5)/2=4
這裏寫圖片描述
因爲data[4]>data[7]所以插入的位置是4,但是此時折半查找並沒有結束
4 low=4 hight=mid-1=3 因爲此時low>hight所以折半折半查找結束
這裏寫圖片描述
low的位置便是應該插入的位置(該位置滿足data[low]>待插入的值,data[hight]<=待插入的值,或者hight爲-1,也就是插入的位置爲0)
5 將low到i-1的數字都往後移動騰出low的位置將插入值插入,注意備份i位置的值避免被覆蓋後找不回待插入值。
這裏寫圖片描述

package sort;
public class Demo7 {
    public static void main(String[] args) {
        int[] data = new int[]{-23,45,2,-45,9,5,3,65,-24};
        sort(data);
        for (int i = 0; i < data.length; i++) {
            System.out.print(data[i]+" ");
        }
    }
    public static void sort(int[] data){
        int low,hight,mid;
        int tmp;//備份存儲待插入的值
        for (int i = 1; i < data.length; i++) {
            if(data[i]<data[i-1]){
                tmp = data[i];
                low = 0;
                hight = i-1;
                while(low<=hight){
                    mid = (low+hight)/2;
                    if(data[mid]<=tmp){  //當中間值小於等於待插入的值,搜索[mid+1,hight]區間
                        low = mid +1;
                    }else{
                        hight = mid - 1; //當中間值小於等於待插入的值,搜索[low,mid-1]區間
                    }
                }
                //將[low,i-1]區間的值後移動
                for (int j = i-1; j >= low; j--) {
                    data[j+1] = data[j];
                }
                //待插入的值插入
                data[low] =tmp;
            }
        }
    }
}

這裏寫圖片描述

希爾排序(Shell排序)

Shell排序是對直接插入排序的改進,它通過加大插入排序中元素之間的間隔,並在這些有間隔的元素進行插入排序,使得數據項跨度移動,不用一步一步往前比較和移動。
Shell排序算法的關鍵就在於確定h序列的值,h就是間隔多少,序列最小值爲1(這時就是直接插入排序),它們存在h=3*h+1的關係。當對一個數列進行Shell排序時,h的值爲多少開始比較合適?h剛好大於數列長度除於3。

int h=1;
while(h<=arrayLength/3){
  h = 3*h+1;
}
//得到的h的值就是Shell排序的增量

得到了Shell排序的增量h序列值後,就從第h個後面數字開始對前面間隔h的值進行插入排序。
例如對-23,45,2,-45,9,5,3,65,-24進行Shell排序
1.長度爲9,則可以計算出增量爲4
2.從第4個後面數字(這裏就是9)開始對前面間隔4的值進行插入排序
這裏寫圖片描述

package sort;
public class Demo5 {
    public static void main(String[] args) {
        int[] num = new int[]{-23,45,2,-45,9,5,3,65,-24};
        sort(num);
    }
    public static void sort(int[] data){
        int h = 1;//增量最小爲1
        int tmp;//存儲待插入的值
        while(h<=data.length/3){ //計算Shell的最大增量
            h = h * 3 + 1;
        }
        while(h>=1){
            //從第h後面的數字開始對前面的間隔爲h的數字進行插入排序,也就是從第h+1個開始,下標爲h
            for(int i = h; i<data.length; i++){
                tmp = data[i];
                if(data[i-h]>tmp){
                    int j = i-h;
                    //對前面的間隔爲h的數字進行插入排序,,,當爲1時就是直接插入排序了
                    for (; j>=0&&data[j]>tmp; j=j-h) {
                        data[j+h] = data[j];//數據往後移動,間隔爲h
                    }
                    data[j+h] = tmp;//這裏加上h是因爲循環最後還減多了一個h
                }
            }
            h = (h-1)/3;//重新計算h的值,尋找小一點的增量

            //打印出來看看,每一趟的Shell排序
            for (int j = 0; j < data.length; j++) {
                System.out.print(data[j]+" ");
            }
            System.out.println();
        }
    }
}

這裏寫圖片描述

三種插入排序的時間複雜度和空間複雜度

插入排序 時間複雜度 空間複雜度
直接插入排序 O(n^2) O(1)
折半插入排序 O(n^2) O(1)
希爾排序 O(n^3/2)~O(n^7/6) O(1)

——————————————————————————–

關注微信公衆號“閱享屋”可獲取900G IT教學視頻和JAVA、前端電子書籍
這裏寫圖片描述

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