個人筆記之插入排序

插入排序

  • 插入排序包括直接插入、折半插入、希爾排序;
  • 任何一種插入排序的每趟排序都不會產生全局有序區;

排序算法的穩定性:是指若是待排序的表中存在多個關鍵字相同的元素,通過排序後這些元素之間的相對次序保持不變,則這種排序方法是穩定的;反之是不穩定的;html

直接插入

  • 時間複雜度 O(n^2) 屬於穩定的排序;
  • 取無序區開頭元素a[ j ]插到有序區的適當位置;
  • 在有序區從後往前找,凡是大於a[ j ]的均後移一個位置,直到找到一個最大的小於等於a[ j ]的元素位置,將a[ j ]插入到它後面;

private static void directInsertSort1(int[] a) {
    //從第二個元素開始,將元素插入到已排好的數組中
    for (int i = 1; i < a.length; i++) {
        int key = a[i];//要插入的值
        int j = i - 1;//從已排好序的數組的最後一個元素向左開始比較
        while (a[j] > key && j >= 0) {//找到最大的小於等於key的值的位置j,並將大於key的值後移
            a[j + 1] = a[j];
            j--;
        }
        //此時的j表明着插入位置的左邊位置下標,即有序區中最大的小於等於key的值的位置;
        a[j + 1] = key;
    }
}複製代碼

如下爲參考連接,大佬在文章裏面有直接插入排序的動圖演示,建議看一下

折半插入

  • 時間複雜度 O(n^2) 屬於穩定的排序;
  • 用折半查找方法先在有序區找到插入位置,再經過移動元素進行插入;

private static void binaryInsertSort(int arr[]) {
     int i, j, half, low,high,key;
     int length=arr.length;
     for (i = 1; i < length; i++) {//從第二個元素開始遍歷
         low = 0;
         high = i - 1;//有序區的最後一個元素下標
         key = arr[i];//要插入的元素
         //折半查找插入位置
         while (low <= high) {//跳出循環時low-high==1
             half = (low + high) / 2;
             if (arr[half] > key) {
                 high = half - 1;
             } else {
                 low = half + 1;
             }
         }
        /*此時,由於最終致使low>high的緣由是: 在二者相遇以後low在half的基礎上增長1或者high在half的基礎上減小1, 因此low-high==1; 倒回循環中: 對high的最後一次操做後,half在high右邊,且arr[half]>key,故arr[high+1]>key; 對low的最後一次操做後,half在low的左邊,且arr[half]<=key,故arr[low-1]<=key; 又由於low=high+1,因此a[low]>key且a[high]<=key 因此low即爲插入位置*/
         for (j = i - 1; j >= low; j--) {//移動插入位置以後的元素
             arr[j + 1] = arr[j];
             }
         //插入元素
         arr[low] = key;
     }
 }複製代碼

希爾排序

  • 時間複雜度 O(n) 屬於不穩定的排序;
  • 經過某個增量gap,每隔gap取一個數組元素分到一個組,而後在組內進行插入排序,隨後逐步縮小增量,繼續按組進行插入排序操做;隨着增量逐漸減小,每組包含的關鍵詞愈來愈多,當增量減至1時,整個文件恰被分紅一組,算法便終止。


//希爾排序 針對有序序列在插入時採用交換法
private static void sort(int[] arr) {
    //1.逐步縮小增量gap
    for (int gap = arr.length / 2; gap > 0; gap /= 2) {
        //2.從第gap個元素,逐個對其所在組進行直接插入排序操做
        for (int i = gap; i < arr.length; i++) {
            int j = i;
            //3.交換,插入排序採用交換法
            while (j - gap >= 0 && arr[j] < arr[j - gap]) {
                swap(arr, j, j - gap);
                j -= gap;
            }
        }
    }
}
//交換數組元素,注意這個交換函數沒有用臨時變量!!!
private static void swap(int[] arr, int a, int b) {
    arr[a] = arr[a] + arr[b];
    arr[b] = arr[a] - arr[b];
    arr[a] = arr[a] - arr[b];
}複製代碼

如下爲參考文章,大佬講的也比較詳細,並且還列舉了希爾排序的另外一種實現方法,建議看一下:java

參考:www.cnblogs.com/chengxiao/p…
算法

相關文章
相關標籤/搜索