Java排序算法之<希爾排序>

目錄

1、希爾排序介紹

1.1、定義

1.2、核心思想

2、希爾排序的流程

第 1 輪:gap = 4

第 2 輪:gap = 2

第 3 輪:gap = 1

3、希爾排序的實現

4、時間復雜度分析

5、希爾排序的優缺點

6、適用場景


前言

????????希爾排序(Shell Sort)是一種基于插入排序的高效排序算法,由 Donald Shell 在 1959 年提出。

gap(間隔)是希爾排序的核心,它決定了如何將數組分成若干子序列進行插入排序。

  • 初始?gap?較大(如?n/2),逐步縮小,直到?gap = 1(此時就是普通插入排序)。

  • 每次按?gap?分組后,對每組進行獨立的插入排序。

gap的作用:

  1. gap?的作用

    • 控制分組的間隔,讓元素能“長距離跳躍”,減少后續操作次數。

  2. 子序列的劃分

    • 每隔?gap?個元素取一個值,形成一組,組內進行插入排序。

  3. 為什么快?

    • 大步長讓數據快速接近有序,小步長最終精細化調整。


1、希爾排序介紹

1.1、定義

????????它通過引入分組間隔(gap)來優化插入排序的性能,使得元素能夠更快地移動到正確的位置,從而減少比較和交換的次數。

1.2、核心思想

1、分組插入排序

將整個數組按照一定的間隔(gap)分成若干子序列,對每個子序列進行插入排序。

2、逐步縮小間隔

隨著排序的進行,gap 不斷縮小,直到 gap = 1(此時相當于普通的插入排序)。

3、最終排序

當 gap = 1 時,數組已經基本有序,插入排序的效率會非常高(接近 O(n))。

為什么比普通插入排序快?

? ? ? ? 插入排序在數據基本有序時效率很高(接近 O(n)),但在完全逆序時效率很低(O(n2))。

????????希爾排序通過先讓數據“大致有序”再執行插入排序,從而顯著提高性能。


2、希爾排序的流程

如下圖所示:

示例:

  1. 選擇一個 gap 序列(如?n/2, n/4, ..., 1)。

  2. 對每個 gap 值,將數組分成若干子序列,并對每個子序列進行插入排序。

  3. 逐步縮小 gap,重復上述過程,直到 gap = 1 完成最終排序。

示例(gap = 4, 2, 1):

原始數組:[8, 3, 6, 2, 1, 9, 5, 7, 4]

假設數組為?[8, 3, 6, 2, 1, 9, 5, 7, 4],長度為?n = 9
我們以?Shell 原始序列gap = n/2, n/4, ..., 1)為例:

第 1 輪:gap = 4

  • 將數組按間隔 4 分組,即每隔 4 個元素取一個元素,形成子序列:

    • 子序列 1:arr[0],?arr[4],?arr[8]?→?[8, 1, 4]

    • 子序列 2:arr[1],?arr[5]?→?[3, 9](因為?arr[9]?越界,停止)

    • 子序列 3:arr[2],?arr[6]?→?[6, 5]

    • 子序列 4:arr[3],?arr[7]?→?[2, 7]

  • 對每個子序列進行插入排序

    • [8, 1, 4]?→?[1, 4, 8]

    • [3, 9]?→?[3, 9](已有序)

    • [6, 5]?→?[5, 6]

    • [2, 7]?→?[2, 7](已有序)

  • 排序后數組
    將子序列按原位置寫回數組:

    • arr[0]=1,?arr[4]=4,?arr[8]=8?→?[1, 3, 5, 2, 4, 9, 6, 7, 8]

第 2 輪:gap = 2

  • 按間隔 2 分組

    • 子序列 1:arr[0],?arr[2],?arr[4],?arr[6],?arr[8]?→?[1, 5, 4, 6, 8]

    • 子序列 2:arr[1],?arr[3],?arr[5],?arr[7]?→?[3, 2, 9, 7]

  • 插入排序

    • [1, 5, 4, 6, 8]?→?[1, 4, 5, 6, 8](交換 5 和 4)

    • [3, 2, 9, 7]?→?[2, 3, 7, 9](交換 3 和 2,然后 9 和 7)

  • 排序后數組[1, 2, 4, 3, 5, 7, 6, 9, 8]

第 3 輪:gap = 1

  • 此時就是普通插入排序,但數組已基本有序:

    • 從?i=1?開始,逐個將元素插入到左側已排序部分。

    • 最終結果:[1, 2, 3, 4, 5, 6, 7, 8, 9]


3、希爾排序的實現

代碼示例如下:

import java.util.Arrays;public class ShellSort {/*** 希爾排序(Shell Sort)* @param arr 待排序數組*/public static void shellSort(int[] arr) {if (arr == null || arr.length <= 1) {return; // 如果數組為空或長度≤1,無需排序}int n = arr.length;// 1. 初始化間隔(gap),這里使用 Shell 原始序列:n/2, n/4, ..., 1for (int gap = n / 2; gap > 0; gap /= 2) {// 2. 對每個子序列進行插入排序(從 gap 開始,逐步向右掃描)for (int i = gap; i < n; i++) {int temp = arr[i]; // 當前待插入元素int j;// 3. 插入排序邏輯:比 temp 大的元素向后移動for (j = i; j >= gap && arr[j - gap] > temp; j -= gap) {arr[j] = arr[j - gap]; // 較大的元素后移}// 4. 將 temp 插入到正確位置arr[j] = temp;}// (可選)打印每輪排序后的數組,方便理解過程System.out.println("Gap = " + gap + ": " + Arrays.toString(arr));}}public static void main(String[] args) {int[] arr = {8, 3, 6, 2, 1, 9, 5, 7, 4};System.out.println("原始數組: " + Arrays.toString(arr));shellSort(arr);System.out.println("排序后數組: " + Arrays.toString(arr));}
}

關鍵步驟說明

  1. 初始化間隔(gap)

    • 初始?gap = n / 2(Shell 原始序列),之后每次縮小為?gap / 2,直到?gap = 1

    • 例如,數組長度?n = 9,則?gap?序列為?4 → 2 → 1

  2. 子序列插入排序

    • 從?i = gap?開始,逐步向右掃描,對每個子序列進行插入排序。

    • 示例gap = 4):

      • 子序列 1:arr[0],?arr[4],?arr[8](即?8, 1, 4?→ 排序后?1, 4, 8

      • 子序列 2:arr[1],?arr[5](即?3, 9?→ 排序后?3, 9

      • 子序列 3:arr[2],?arr[6](即?6, 5?→ 排序后?5, 6

      • 子序列 4:arr[3],?arr[7](即?2, 7?→ 排序后?2, 7

  3. 插入排序邏輯

    • 類似普通插入排序,但步長是?gap?而不是?1

    • 如果?arr[j - gap] > temp,則向后移動元素。

  4. 插入最終位置

    • 將?temp?放到正確的位置?arr[j]

輸出:

原始數組: [8, 3, 6, 2, 1, 9, 5, 7, 4]
Gap = 4: [1, 3, 5, 2, 4, 9, 6, 7, 8]
Gap = 2: [1, 2, 4, 3, 5, 7, 6, 9, 8]
Gap = 1: [1, 2, 3, 4, 5, 6, 7, 8, 9]
排序后數組: [1, 2, 3, 4, 5, 6, 7, 8, 9]


4、時間復雜度分析

如下所示:

常見 gap 序列的影響:

  • Shell 原始序列(n/2, n/4, ..., 1):最壞 O(n2)。

  • Hibbard 序列(1, 3, 7, 15, ..., 2^k -1):最壞 O(n^(3/2))。

  • Knuth 序列(1, 4, 13, 40, ..., (3^k -1)/2):平均 O(n^(3/2))。

????????Java 的?Arrays.sort()?在特定情況下會使用希爾排序的變種(如 TimSort 結合插入排序優化)。


5、希爾排序的優缺點

1、優點

  • 比普通插入排序快,尤其是對中等規模數據(n ≤ 10?)。

  • 原地排序,空間復雜度 O(1)。

  • 適用于部分有序數據,性能接近 O(n)。

2、缺點

  • 不穩定排序(可能改變相同元素的相對順序)。

  • 時間復雜度依賴 gap 序列,選擇不當可能退化到 O(n2)。


6、適用場景

  • 中小規模數據排序(比插入排序更快,比快速排序/歸并排序更節省內存)。

  • 嵌入式系統或內存受限環境(因為它是原地排序)。

  • 部分有序數據(性能接近線性時間)。


總結

  • 希爾排序是插入排序的優化版本,通過分組排序減少元素移動次數。

  • 時間復雜度介于 O(n log n) ~ O(n2),取決于 gap 序列的選擇。

  • 適用于中小規模數據,在特定情況下比快速排序/歸并排序更高效。

如果你需要中等規模數據進行排序,并且希望節省內存希爾排序是一個不錯的選擇!


參考文章:

1、六大排序算法:插入排序、希爾排序、選擇排序、冒泡排序、堆排序、快速排序-CSDN博客https://blog.csdn.net/weixin_50886514/article/details/119045154?ops_request_misc=%257B%2522request%255Fid%2522%253A%25220faf03d22b2d125d5f49a4649ad59c85%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=0faf03d22b2d125d5f49a4649ad59c85&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-119045154-null-null.142^v102^control&utm_term=%E5%86%92%E6%B3%A1%E6%8E%92%E5%BA%8F&spm=1018.2226.3001.4187

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/90911.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/90911.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/90911.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

c++加載qml文件

這里展示了c加載qml文件的三種方式以及qml文件中根節點的訪問準備在創建工程的初期&#xff0c;遇到了一個問題&#xff0c;cmake文件以前都是系統自動生成的&#xff0c;不需要我做過多的操作修改&#xff0c;但是&#xff0c;加載qml的程序主函數是需要用到QGuiApplication&a…

007TG洞察:GPT-5前瞻與AI時代競爭力構建:技術挑戰與落地路徑

最近&#xff0c;GPT-5 即將發布的消息刷爆了科技圈&#xff0c;更讓人期待的是&#xff0c;GPT-6 已經悄悄啟動訓練了&#xff0c;OpenAI 的奧特曼表示對未來1-2年的模型充滿信心&#xff0c;預測AI將進化為能夠發現新知識的“AI科學家”。面對日益強大的通用AI&#xff0c;企…

Windows下編譯OpenVDB

本文記錄在Windows下編譯OpenVDB的流程。 零、環境 操作系統Windows 11VS Code1.92.1Git2.34.1MSYS2msys2-x86_64-20240507Visual StudioVisual Studio Community 2022CMake3.22.1 一、編譯 1.1 下載 git clone https://github.com/AcademySoftwareFoundation/openvdb.git …

react 內置hooks 詳細使用場景,使用案例

useState場景&#xff1a;組件中管理局部狀態&#xff0c;如表單值、開關、計數器等。const [count, setCount] useState(0); return <button onClick{() > setCount(count 1)}>Click {count}</button>;useEffect 場景&#xff1a;組件掛載時執行副作用&#…

從0到1學Pandas(九):Pandas 高級數據結構與操作

目錄一、探秘多級索引1.1 創建多級索引1.2 多級索引操作1.3 索引轉換二、探索 Panel 與 xarray2.1 Panel 數據結構2.2 xarray 庫2.3 高維數據操作三、時間序列高級應用3.1 時區處理3.2 時間序列重采樣與頻率轉換3.3 時間序列分解與預測四、數據透視與重塑高級技巧4.1 復雜透視表…

C# 圖像轉換實戰:Bitmap 轉 BitmapSource 的 2 種方法

C# 圖像轉換實戰:Bitmap 轉 BitmapSource 的 2 種方法 引言 兩種轉換方法的完整實現 1. 基于GDI句柄的直接轉換 (ToBitmapSourceFast) 2. 基于內存流的編碼轉換 (ToBitmapSourceSafe) 方法對比與選型指南 避坑指南 GDI句柄泄漏問題 圖像顯示不完整 多線程訪問圖像引發異常 不同…

Spring Boot 整合 Spring MVC:自動配置與擴展實踐

Spring MVC 作為 Java Web 開發的核心框架&#xff0c;在傳統 SSM 項目中需要大量 XML 配置&#xff08;如 DispatcherServlet、視圖解析器等&#xff09;。而 Spring Boot 通過 "自動配置" 特性&#xff0c;簡化了 Spring MVC 的整合過程&#xff0c;同時保留了靈活…

print(“\033[31m紅\033[32m綠\033[34m藍\033[0m默認色“)

可以讓python的終端字體有著不一樣的顏色。代碼&#xff1a;print("\033[31m紅\033[32m綠\033[34m藍\033[0m默認色")效果&#xff1a;

LNMP-zblog分布式部署

一、準備3臺主機&#xff08;rocky8&#xff09;下載相應服務[rootnginx ~]# yum install -y nginx nfs-utils[rootphp ~]# yum install -y nfs-utils php-mysqlnd php php-fpm[rootmysql ~]# yum install -y mysql-server二、掛載php端[rootphp ~]# vim /etc/exports [rootphp…

常見代碼八股

1. 利用梯度下降法&#xff0c;計算二次函數yx^2x4的最小值 def target_function(x):return x ** 2 x 4def gradient(x):return 2*x 1x_init 10 x x_init steps 100 lr 0.1 for i in range(100):x x - lr*gradient(x)print(f"最小值 f(x) {target_function(x):.4f…

【深入底層】C++開發簡歷4+4技能描述6

簡歷書寫 熟悉C的封裝、繼承、多態&#xff0c;STL常用容器&#xff0c;熟悉C11的Lambda表達式、智能指針等&#xff0c;熟悉C20協程語法&#xff0c;具有良好的編碼習慣與文檔能力。 回答思路 這里是基本上就是要全會&#xff0c;考察的問題也很固定&#xff0c;stl這塊可以定…

forest遠程調用注意事項

1、如果在項目中&#xff0c;同時依賴了其中多個框架&#xff0c;那么按 Fastjson2 > Fastjson > Jackson > Gson 這樣的優先級來判斷&#xff0c;Forest 會以優先級最高的框架作為 JSON 轉換器。2、Forest 支持哪幾種 JSON 框架&#xff1f;A: 支持 Jackson、Gson、F…

網絡資源模板--基于Android Studio 實現的新聞App

目錄 一、測試環境說明 二、項目簡介 三、項目演示 四、部設計詳情&#xff08;部分) 登錄頁 首頁 五、項目源碼 一、測試環境說明 電腦環境 Windows 11 編寫語言 JAVA 開發軟件 Android Studio (2020) 開發軟件只要大于等于測試版本即可(近幾年官網直接下載也可…

通過Location API精準獲取位置信息并優化定位精度!

&#x1f44b; 你好&#xff0c;歡迎來到我的博客&#xff01;我是【菜鳥不學編程】 ?? 我是一個正在奮斗中的職場碼農&#xff0c;步入職場多年&#xff0c;正在從“小碼農”慢慢成長為有深度、有思考的技術人。在這條不斷進階的路上&#xff0c;我決定記錄下自己的學習與成…

構建可擴展的狀態系統:基于 ArkTS 的模塊化狀態管理設計與實現

摘要 在 HarmonyOS 的日常開發中&#xff0c;很多人都會遇到一個問題&#xff1a;多個頁面之間的數據狀態如何共享&#xff1f;尤其是在組件結構越來越復雜的場景下&#xff0c;如果還用傳統方式來傳值&#xff0c;不僅代碼混亂&#xff0c;維護也很吃力。 為了解決這個問題&am…

重生之我在暑假學習微服務第二天《MybatisPlus-下篇》

本系列參考黑馬程序員微服務課程&#xff0c;有興趣的可以去查看相關視頻&#xff0c;本系列內容采用漸進式方式講解微服務核心概念與實踐方法&#xff0c;每日更新確保知識點的連貫性。通過系統化學習路徑幫助開發者掌握分布式系統構建的關鍵技術。讀者可通過平臺訂閱功能獲取…

系統整理Python的條件語句和常用方法

Python 的條件語句&#xff08;if 語句&#xff09;是控制程序流程的基礎之一&#xff0c;結構清晰、語法簡潔&#xff0c;非常適合初學者掌握。一、基本語法結構if 條件:執行代碼塊1 elif 條件2:執行代碼塊2 else:執行代碼塊3示例&#xff1a;score 85if score > 90:print…

記錄個IAR程序下載后硬件復位不運行,必須斷電復位才運行的問題

【問題測試】有個F407的跑馬燈的例子&#xff0c;是MDK和IAR兩個版本&#xff0c;MDK版本的例子下載并復位后可以正常看到LED閃爍&#xff0c;而IAR的例子下進去后&#xff0c;不會閃爍。使用TOOL的上位機內核寄存器監測工具測試發現&#xff0c;硬件復位后竟然還在調試狀態&am…

觀察者模式(Observer Pattern)和 發布-訂閱模式(Publisher-Subscriber Pattern)

你對 觀察者模式&#xff08;Observer Pattern&#xff09;和 發布-訂閱模式&#xff08;Publisher-Subscriber Pattern&#xff09;的描述是非常準確的&#xff0c;并且闡明了它們的核心區別。為了幫助你更好地理解這兩者的細微差異&#xff0c;下面是一個更詳細的對比分析&am…

2025年接口技術的十字路口:當MCP遇見REST、GraphQL與gRPC

在當今這個由數據驅動、萬物互聯的時代&#xff0c;應用程序接口&#xff08;API&#xff09;已成為現代軟件架構的基石。它們是不同服務之間溝通的橋梁&#xff0c;支撐著從網頁應用到復雜的微服務生態系統的一切。長久以來&#xff0c;開發者們在REST、GraphQL和gRPC這幾種主…