希爾排序:突破傳統排序的邊界

一、算法思想

希爾排序(Shell Sort),也被叫做縮小增量排序,是插入排序的一種改進版本。希爾排序的核心在于先將整個待排序的記錄序列分割成若干個子序列,分別進行直接插入排序。隨著增量逐漸減小,子序列的長度慢慢增加,整個序列會變得越來越接近有序。當增量減至 1 時,整個序列就會被合并為一個,再進行一次直接插入排序,最終完成整個排序過程。

與插入排序對比

插入排序在處理部分有序的數組時效率更高,而希爾排序正是利用了這一特性。它通過分組預排序,讓數組先達到部分有序的狀態,最后再進行一次插入排序,從而減少了元素移動的次數。

算法步驟

  1. 選擇增量序列:確定一個遞減的增量序列,常用的增量序列有希爾增量(n/2, n/4, ..., 1)、Knuth 增量(3k +1)等。
  2. 按增量分組:根據當前增量將數組分成若干個子序列,每個子序列的元素間隔為當前增量。
  3. 對子序列排序:對每個子序列分別進行插入排序。
  4. 減小增量:增量逐漸減小,重復步驟 2 和 3,直到增量為 1。
  5. 最終排序:當增量為 1 時,整個數組作為一個子序列進行一次插入排序,此時數組已基本有序,插入排序效率較高。

二、手動排序示例

下面以數組?[8, 9, 1, 7, 2, 3, 5, 4, 6, 0]?為例,詳細展示希爾排序的過程。這里我們采用希爾增量序列(初始增量為數組長度的一半,之后每次減半)。

初始數組

[8, 9, 1, 7, 2, 3, 5, 4, 6, 0]

第一趟排序(增量為 5)

將數組分成 5 個子序列:

  • 子序列 1:[8, 3] → 排序后 [3, 8]
  • 子序列 2:[9, 5] → 排序后 [5, 9]
  • 子序列 3:[1, 4] → 排序后 [1, 4]
  • 子序列 4:[7, 6] → 排序后 [6, 7]
  • 子序列 5:[2, 0] → 排序后 [0, 2]

排序后的數組:

[3, 5, 1, 6, 0, 8, 9, 4, 7, 2]

第二趟排序(增量為 2)

將數組分成 2 個子序列:

  • 子序列 1:[3, 1, 0, 9, 7] → 排序后 [0, 1, 3, 7, 9]
  • 子序列 2:[5, 6, 8, 4, 2] → 排序后 [2, 4, 5, 6, 8]

排序后的數組:

[0, 2, 1, 4, 3, 5, 7, 6, 9, 8]

第三趟排序(增量為 1)

此時進行直接插入排序:

[0, 2, 1, 4, 3, 5, 7, 6, 9, 8] → [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

最終得到有序數組:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

三、C 語言實現代碼

下面是希爾排序的 C 語言實現,采用希爾增量序列:

#include <stdio.h>// 希爾排序函數
void shellSort(int arr[], int n) {// 初始增量為數組長度的一半,之后每次減半,直到增量為1for (int gap = n / 2; gap > 0; gap /= 2) {// 對每個子序列進行插入排序for (int i = gap; i < n; i++) {int temp = arr[i];int j;// 插入排序邏輯:將當前元素插入到其所在子序列的正確位置for (j = i; j >= gap && arr[j - gap] > temp; j -= gap) {arr[j] = arr[j - gap];}arr[j] = temp;}}
}// 打印數組函數
void printArray(int arr[], int n) {for (int i = 0; i < n; i++) {printf("%d ", arr[i]);}printf("\n");
}// 主函數
int main() {int arr[] = {8, 9, 1, 7, 2, 3, 5, 4, 6, 0};int n = sizeof(arr) / sizeof(arr[0]);printf("原始數組: \n");printArray(arr, n);shellSort(arr, n);printf("排序后的數組: \n");printArray(arr, n);return 0;
}

四、代碼解釋

希爾排序函數?shellSort

  1. 增量序列控制

    • 初始增量?gap?設為數組長度的一半(n/2)。
    • 每輪循環后將增量減半(gap /= 2),直到增量為 1。
  2. 分組插入排序

    • 對于每個增量?gap,將數組分為?gap?個子序列。
    • 對每個子序列進行插入排序,確保元素在各自子序列中有序。
  3. 插入排序優化

    • 使用臨時變量?temp?保存當前元素。
    • 通過比較和移動元素,找到?temp?應插入的位置。

主函數?main

  1. 數組初始化:定義待排序的數組?arr
  2. 排序前輸出:調用?printArray?函數顯示原始數組。
  3. 調用排序:調用?shellSort?函數對數組進行排序。
  4. 排序后輸出:再次調用?printArray?函數顯示排序后的數組。

五、算法復雜度與穩定性

時間復雜度

希爾排序的時間復雜度與增量序列的選擇有關,不同的增量序列會導致不同的時間復雜度:

  • 最壞情況:希爾增量序列下為 O (n2)
  • 平均情況:取決于增量序列,可能達到 O (n^1.3) 或更好
  • 最好情況:當數組已經有序時為 O (n)

空間復雜度

希爾排序只需要常數級的額外空間,因此空間復雜度為 O (1)。

穩定性

希爾排序是一種不穩定的排序算法,因為在不同的子序列插入排序過程中,相同元素的相對順序可能會發生改變。

六、希爾排序的優缺點

優點

  1. 高效性:對于中等規模的數據,希爾排序的性能通常優于直接插入排序和選擇排序。
  2. 空間效率:只需要常數級的額外空間。
  3. 實現簡單:代碼結構相對簡單,易于理解和實現。

缺點

  1. 復雜度分析困難:時間復雜度依賴于增量序列的選擇,難以精確分析。
  2. 不穩定性:不適合需要保持元素相對順序的應用場景。

七、適用場景

希爾排序適用于以下場景:

  • 數據量中等且不需要穩定性的排序任務。
  • 對內存使用有限制的環境,因為它只需要 O (1) 的額外空間。
  • 作為更復雜排序算法的預處理步驟。

希爾排序通過巧妙的分組策略,打破了傳統插入排序的性能瓶頸,為排序算法的發展開辟了新的思路。在實際應用中,合理選擇增量序列可以顯著提高希爾排序的性能。

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

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

相關文章

Kafka事務消息與Exactly-Once語義實戰指南

Kafka事務消息與Exactly-Once語義實戰指南 在分布式微服務或大數據處理場景中&#xff0c;消息隊列常被用于異步解耦、流量削峰和系統伸縮。對于重要業務消息&#xff0c;尤其是金融、訂單、庫存等場景&#xff0c;消息的精確投遞&#xff08;Exactly Once&#xff09;和事務一…

26.將 Python 列表拆分為多個小塊

將 Python 列表拆分為多個小塊(Chunk a List) ?? 場景 1:按份數 chunk_into_n(lst, n) 將一個列表平均拆分為 n 個塊。如果不能整除,最后一塊會包含剩余元素。 ? 示例代碼 from math import ceildef chunk_into_n(lst, n):size = ceil(len

18.理解 Python 中的切片賦值

1. 切片語法回顧 標準切片語法格式為: [start_at : stop_before : step]start_at:起始索引(包含)stop_before:結束索引(不包含)step:步長(默認為 1)例如: lst = [1, 2,

論文 視黃素與細胞修復

王偉教授發布&#xff0c;通過對比兔子和老鼠耳朵穿孔后的復原&#xff0c;控制變量法發現了 視黃素對細胞修復的影響

JavaScript 的執行上下文

當 JS 引擎處理一段腳本內容的時候,它是以怎樣的順序解析和執行的?腳本中的那些變量是何時被定義的?它們之間錯綜復雜的訪問關系又是怎樣創建和鏈接的?要解釋這些問題,就必須了解 JS 執行上下文的概念。 JavaScript引擎: JavaScript引擎是一個計算機程序,它接收JavaScri…

掉線監測-tezos rpc不能用,改為殘疾網頁監測

自從有了編程伴侶&#xff0c;備忘的需求變得更低了&#xff0c;明顯不擔心記不住語法需要記錄的情景。然而還是保持習慣&#xff0c;就當寫日記吧&#xff0c;記錄一下自己時不時在瞎搗騰啥。tm&#xff0c;好人誰記日記。就是監控灰色各自前緊挨著出現了多少紅色格子。一共查…

Spark Expression codegen

Expression codegen src/main/scala/org/apache/spark/sql/catalyst/expressions/Expression.scala def genCode(ctx: CodegenContext): ExprCode = {ctx.subExprEliminationExprs.get(ExpressionEquals(

Axios方法完成圖書管理頁面完整版

一、目的 需要實現的功能有包括&#xff1a; 從服務器發送請求&#xff0c;獲取圖書列表并渲染添加新圖書編輯現有圖書信息刪除圖書以上每一步都實現與服務器存儲數據同步更改 二、基礎配置 引入Axios庫&#xff1a; <script src"https://cdn.jsdelivr.net/npm/ax…

SQLlite下載以及簡單使用

SQLite Download Page cd D:\WK\2025\StudentManagerSystem\sqlite D: entManagerSystem\sqlite>sqlite3.exe 所建庫的名字.db 一&#xff1a;命令 <1>打開某個數據庫文件中 sqlite3 test.db<2>查看所有的命令介紹(英文) .help<3>退出當前數據庫系統 .qu…

函數柯里化詳解

一、函數柯里化&#xff1a; 是一種高階函數技術&#xff0c;它將一個多參數函數轉換為一系列單參數函數的鏈式調用。 核心概念 定義&#xff1a;將一個函數 f(a, b, c) 轉換為 f(a)(b)© 的形式 **本質&#xff1a;**通過閉包保存參數&#xff0c;實現分步傳參 關鍵特征&a…

C++11:constexpr 編譯期性質

C11&#xff1a;constexpr & 編譯期性質常量表達式 constexpr變量IiteralType函數自定義字面量參數匹配與重載規則靜態斷言常量表達式 constexpr const expression常量表達式&#xff0c;是C11引入的新特性&#xff0c;用于將表達式提前到編譯期進行計算&#xff0c;從而減…

【每天一個知識點】多模態信息(Multimodal Information)

常用的多模態信息&#xff08;Multimodal Information&#xff09;指的是來源于多種感知通道/數據類型的內容&#xff0c;這些信息可以被整合處理&#xff0c;以提升理解、推理與生成能力。在人工智能和大模型系統中&#xff0c;典型的多模態信息主要包括以下幾類&#xff1a;?…

iOS 抓包工具精選對比:不同調試需求下的工具適配策略

iOS 抓包痛點始終存在&#xff1a;問題不是“抓不抓”&#xff0c;而是“怎么抓” 很多開發者都遇到過這樣的情況&#xff1a; “接口沒有返回&#xff0c;連日志都沒打出來”“模擬器正常&#xff0c;真機無法請求”“加了 HTTPS 雙向認證&#xff0c;抓不到了”“明明設置了 …

圖像修復:深度學習實現老照片劃痕修復+老照片上色

第一步&#xff1a;介紹 1&#xff09;GLCIC-PyTorch是一個基于PyTorch的開源項目&#xff0c;它實現了“全局和局部一致性圖像修復”方法。該方法由Iizuka等人提出&#xff0c;主要用于圖像修復任務&#xff0c;能夠有效地恢復圖像中被遮擋或損壞的部分。項目使用Python編程語…

css 邊框顏色漸變

border-image: linear-gradient(90deg, rgba(207, 194, 195, 1), rgba(189, 189, 189, 0.2),rgba(207, 194, 195, 1)) 1;

本地 LLM API Python 項目分步指南

分步過程 需要Python 3.9 或更高版本。 安裝 Ollama 并在本地下載 LLM 根據您的操作系統&#xff0c;您可以從其網站下載一個或另一個版本的 Ollama 。下載并啟動后&#xff0c;打開終端并輸入以下命令&#xff1a; ollama run llama3此命令將在本地拉取&#xff08;下載&…

日本的所得稅計算方式

? 【1】所得稅的計算步驟&#xff08;概要&#xff09; 日本的所得稅大致按照以下順序來計算&#xff1a; 1?? 統計收入&#xff08;銷售額、工資等&#xff09; 2?? 扣除必要經費等&#xff0c;得到「所得金額」 3?? 扣除各類「所得控除」&#xff08;所得扣除&#xf…

【langchain4j篇01】:5分鐘上手langchain4j 1.1.0(SpringBoot整合使用)

目錄 一、環境準備 二、創建項目、導入依賴 三、配置 application.yml 四、注入Bean&#xff0c;開箱即用 五、日志觀察 一、環境準備 首先和快速上手 Spring AI 框架一樣的前置條件&#xff1a;先申請一個 apikey &#xff0c;此部分步驟參考&#xff1a;【SpringAI篇01…

js運算符

運算符 jarringslee*賦值運算符 - / 對變量進行賦值的運算符&#xff0c;用于簡化代碼。左邊是容器&#xff0c;右邊是值一元運算符正號 符號- 賦予數據正值、負值自增 自減– 前置和后置&#xff1a;i和i&#xff1a;一般情況下習慣使用后置i&#xff0c;兩者在單獨…

next.js 登錄認證:使用 github 賬號授權登錄。

1. 起因&#xff0c; 目的: 一直是這個報錯。2. 最終效果&#xff0c; 解決問題&#xff0c;能成功登錄、體驗地址&#xff1a;https://next-js-gist-app.vercel.app/代碼地址&#xff1a; https://github.com/buxuele/next-js-gist-app3. 過程: 根本原因: github 的設置&…