首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

插入排序與希爾排序:原理、代碼實現、時間複雜度深度分析

     編輯:Java 綜合教學

一、插入排序

核心思想

將陣列分為「已排序區」與「未排序區」。初始已排序區僅含首元素。每輪從未排序區取出首元素 key,在已排序區從右向左掃描,將大於 key 的元素右移,騰出位置插入 key。類似撲克牌整理手牌。

動圖演示

插入排序過程圖1

插入排序過程圖2

C 語言實現

void InsertSort(int *A, int n) {
    int i, j, key;
    for (i = 1; i < n; i++) {
        key = A[i];
        for (j = i; j > 0 && key < A[j-1]; j--) {
            A[j] = A[j-1]; // 右移
        }
        A[j] = key;
    }
}

時間複雜度分析

情況比較次數移動次數總體
最好(已有序)N-10O(N)
最壞(逆序)N(N-1)/2N(N-1)/2O(N²)
平均~N²/4~N²/4O(N²)

逆序對視角的平均複雜度證明

  1. 定義逆序對:i < j 且 A[i] > A[j]。
  2. 插入排序本質是「交換相鄰元素消除逆序對」,總操作次數 = 逆序對數 + O(N)。
  3. 任意含 N 個互異元素的排列,其逆序對數期望 = N(N-1)/4。
    證明:對任意序列 A,其反序列 A'。任意元素對 (x,y) 必在 A 或 A' 中構成逆序對。總對數 C(N,2)=N(N-1)/2,故 A 平均逆序對 = 一半 = N(N-1)/4。
  4. 故平均時間 O(N²)。

適用場景

  • 資料量小(< 50)
  • 資料近乎有序(如線上插入新元素)
  • 作為快速排序、歸併排序的小區間基礎排序(閾值 16~32)

二、希爾排序

核心改進

插入排序只比較相鄰元素,移動代價大。希爾排序引入增量序列 h₁, h₂, ..., hₖ=1,每輪按增量 h 分組進行插入排序,使元素大步長移動,最後一輪 h=1 即普通插入排序,但此時陣列已近乎有序,極快。

增量序列選擇與複雜度

增量序列公式時間複雜度備註
Shell 原始N/2, N/4, ..., 1O(N²)最差,不推薦
Hibbard2ᵏ-1: 1, 3, 7, 15...O(N3/2)較好
Sedgewick1, 5, 19, 41, 109...O(N4/3) 或 O(N7/6)目前最佳實用序列
Pratt2ᵖ3ᑫO(N log²N)常數大,工程少用

C 語言實現(Shell 原始增量)

void ShellSort(int *A, int n) {
    int i, j, inc, key;
    for (inc = n/2; inc > 0; inc /= 2) {
        for (i = inc; i < n; i++) {
            key = A[i];
            for (j = i; j >= inc && key < A[j-inc]; j -= inc) {
                A[j] = A[j-inc];
            }
            A[j] = key;
        }
    }
}

關鍵性質

  • 每輪 h-排序後,陣列滿足 A[i] <= A[i+h],稱為 h-有序。
  • 後續更小增量排序保持已建立的 h-有序性。
  • 非穩定排序(長距離交換可能改變相等元素相對順序)。

總結對比

維度插入排序希爾排序
最好時間O(N)O(N log N) 或 O(N1.5)
最壞時間O(N²)O(N²) (Shell) / O(N1.5) (Hibbard)
平均時間O(N²)O(N1.25~1.5)
空間O(1)O(1)
穩定性穩定不穩定
工程應用小陣列、近乎有序中等規模、嵌入式系統、庫函數備選
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved