異世界歷險之數據結構世界(排序(插入,希爾,堆排))

前言

在這里插入圖片描述

介紹

插入排序

基本知識:
直接插入排序是一種簡單的插入排序法,其基本思想是:
把待排序的記錄按其關鍵碼值的大小逐個插入到一個已經排好序的有序序列中,直到所有的記錄插入完為止,得到一個新的有序序列

在這里插入圖片描述

直接插入排序的特性總結:

  1. 元素集合越接近有序,直接插入排序算法的時間效率越高
  2. 時間復雜度:O(N^2)
  3. 空間復雜度:O(1),它是一種穩定的排序算法
  4. 穩定性:穩定

實現

void InsertSort(int*arr,int n)
{for (int i = 1; i < n; i++){int tmp = arr[i];int end = i - 1;while (tmp < arr[end]){arr[end + 1] = arr[end];end--;}arr[end + 1] = tmp;}}

解析:1.外層 for 循環控制遍歷每個待插入的元素,從下標 1 開始(因為下標 0 視為初始的已排序區)
2. tmp 暫存當前要插入的元素。
end 表示已排序部分的末尾元素下標,用來向左比較尋找插入位置。
3.當當前元素 tmp 小于已排序區的元素 arr[end],說明還沒找到插入位置:
將較大的元素右移一位,給 tmp 騰出空間;
end-- 繼續向左查找。

4.找到插入位置后,將 tmp 放入空出來的位置,即 end + 1

希爾排序

基本知識:
希爾排序法的基本思想是:先選定一個整數,把待排序文件中所有記錄分成個
組,所有距離為的記錄分在同一組內,并對每一組內的記錄進行排序。然后,取,重復上述分組和排序的工作。當到達=1時,所有記錄在統一組內排好序

在這里插入圖片描述

  1. 希爾排序是對直接插入排序的優化。
  2. 當gap > 1時都是預排序,目的是讓數組更接近于有序。當gap == 1時,數組已經 接近有序的了,這樣就會很快。

實現

void ShellSort(int*arr,int n)
{ for(int gap = n/2;gap>0;gap/=2){  for(int i = gap;i<n;i++){ int tmp = arr[i];int end = i-gap;while(end>=0 && arr[end]>tmp){arr[end+gap] =arr[end];end -= gap;}arr[end+gap] = tmp;}}
}
解析
for(int gap = n/2;gap>0;gap/=2)

設定初始間隔 gap = n/2,后續每次縮小一半。
這樣每輪都能把當前數組變得更“接近有序”。
最后當 gap == 1 時,其實就是普通的插入排序,但效率更高!

for (int i = gap; i < n; i++)

從當前 gap 開始往后遍歷數組。
為啥不是 i=0?因為我們要比較 arr[i] 和它 gap 之前的數,即 arr[i - gap],所以 i 至少得 ≥ gap。

arr[end + gap] = arr[end];
end -= gap;

把大的元素往后挪出一個 gap 的位置。
指針繼續往前 gap 個單位看下一個數。

arr[end + gap] = tmp;

找到該插入的位置了,把 tmp 插進去。
完成一個元素在當前 gap 下的插入排序。

實戰演示

數組排序OJ
在這里插入圖片描述

解答
void ShellSort(int*arr,int n)
{ for(int gap = n/2;gap>0;gap/=2){  for(int i = gap;i<n;i++){ int tmp = arr[i];int end = i-gap;while(end>=0 && arr[end]>tmp){arr[end+gap] =arr[end];end -= gap;}arr[end+gap] = tmp;}}
}int* sortArray(int* nums, int numsSize, int* returnSize) {int* arr = (int*)malloc(sizeof(int)*numsSize);for(int i = 0;i<numsSize;i++){arr[i]=nums[i];}InsertSort(arr,numsSize);*returnSize = numsSize;return arr;
}

希爾排序總結:

核心思路:先按大?gap?做分組插入排序,逐步縮小?gap?到?1。
時間復雜度:平均?≈?O(n1·3~n1·?),最壞 O(n2);效率取決于?gap?序列。
空間復雜度:O(1)?原地排序。
穩定性:不穩定,同值元素位置可能改變。

希爾排序補充

1.反向插排希爾
void HalfShellSort(int* arr, int n)
{int gap = 3;for (int i = 0; i < n - gap; i++){int end = i;int tmp = arr[i + gap];while (end >= 0 && arr[end] > tmp){arr[end + gap] = arr[end];end -= gap;}arr[end + gap] = tmp;}
}

差異:

for (int i = 0; i < n - gap; i++)
{int end = i;int tmp = arr[i + gap];
}
for(int i = gap;i < n;i++){ int tmp = arr[i];int end = i-gap;}

解釋:
方案一是正常思維以0為起點,即end為主角,end+gap 是tmp的位置,故為了不越界·i<n-gap。
方案二是以第二個gap為i的開始,即tmp為主角,tmp始終是end的后一個gap,所以i<n,不存在越界問題。

2.多重循環希爾
void ShellSort(int* arr, int n)
{for (int gap = n / 2; gap > 0; gap /= 2){for (int j = 0; j < gap; j++){for (int i = j; i < n - gap; i+=gap){int tmp = arr[i+gap];int end = i;while (end >= 0 && arr[i] > tmp){arr[end + gap] = arr[end];end -= gap;}arr[end + gap] = tmp;}}}
}

差異:

for (int j = 0; j < gap; j++)for (int i = j; i < n - gap; i+=gap)
for(int i = 0;i<n-gap;i++)

方案一比方案二多了一層循環
原因分析: 方案一是以gap將全部分為gap個集合,每個集合內進行希爾排序。
例如:以gap==3 為例:
分為:0開頭集合,1開頭集合,2開頭集合 以這種形式進行排序。
方案二則是按順序一個一個排。
二者沒有任何區別,時間復雜度和空間復雜度一樣。

堆排序

基本知識:
堆排序即利用堆的思想來進行排序,總共分為兩個步驟:

  1. 建堆
    升序:建大堆
    降序:建小堆
  2. 利用堆刪除思想來進行排序

堆的復習
向上調整函數(AdjustUp)
向下調整函數(AdjustDown)
堆插入

實現

1.建堆
方案一:

void AdjustUp(int* arr,int child)
{int parent = (child - 1) / 2;while (child>0){if (arr[child] > arr[parent]){Swap(&arr[child], &arr[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}
}void HeapSort(int*arr,int n)
{for (int i = 1; i < n; i++){AdjustUp(arr, i);}
}

類似于堆插入,從第二個數組中元素開始插入,調整。

方案二:

void AdjustDown(int* arr, int n, int parent)
{int child = 2 * parent + 1;while (child < n){if (child + 1 < n && arr[child] < arr[child + 1]){child++;}if (arr[child] > arr[parent]){Swap(&arr[child], &arr[parent]);parent = child;child = 2 * parent + 1;}else{break;}}
}void HeapSort(int*arr,int n)
{for (int i = (n - 1 - 1) / 2; i >= 0; i--){AdjustDown(arr,n,i);}
}

i == (n-1-1)/2 是尾(最后)葉子的父節點。
向下調整建堆的原理是:
從最后一個非葉子節點開始,逐個對子樹進行向下調整,把局部小堆變成大堆,逐層向上構造,最終整個數組就成了一個大堆結構。

在這里插入圖片描述

總結:
方法一:向上調整(AdjustUp)
從第1個元素往后掃,每插入一個元素就“向上冒泡”一次,維護堆
時間復雜度:O(n log n)
方法二:向下調整(AdjustDown)
從最后一個非葉子節點開始,逐個節點向下調整整個子樹
最終堆頂就是整個數組的最大值(如果建大堆)
時間復雜度:O(n) 更優!

2.排序

void HeapSort(int*arr,int n)
{for (int i = (n - 1 - 1) / 2; i >= 0; i--){AdjustDown(arr,n,i);}int end = n - 1;while (end > 0){Swap(&arr[0], &arr[end]);AdjustDown(arr, end, 0);end--;}
}

在這里插入圖片描述
排序如圖所示。
1.交換根和尾葉子,把大數放在后面。
2.向下調整,在形成大根堆。
3.循環往復。

總結

八大排序我們學了三個,其余的將逐漸補充豐富。

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

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

相關文章

oracle 數據庫中,將幾張表的數據按指定日期范圍實時同步至同一個數據庫的備份表中。

以下是一個Oracle數據庫中實現表數據按指定日期范圍實時同步至備份表的解決方案。這個方案使用存儲過程和觸發器組合實現&#xff1a; 1. 創建備份表結構 首先需要為每張需要備份的表創建對應的備份表&#xff0c;結構與原表相同&#xff1a; -- 為原表創建備份表&#xff08;示…

電腦網絡連接正常,微信、QQ能正常使用,但無法訪問網頁?DNS問題的解決方案和背后原理。

文章目錄1. 問題背景2. 解決方案2.1 手動刷新DNS2.1.1 Windows版本2.1.2 Mac版本2.2 手動設置DNS服務器2.2.1 Windows版2.2.2 Mac版2.3 其他解決方案3. DNS是什么&#xff1f;3.1 詳細解釋DNS3.1.1 A distributed, hierarchical database&#xff08;一個分布式和分層數據庫結構…

【HTML】圖片比例和外部div比例不一致,最大程度占滿

圖片比例和外部div比例不一致&#xff0c;最大程度占滿&#xff0c;并且圖片比例不變 其中1.jpg,2.jpg,1.html在同一目錄 |-----|- 1.jpg|- 2.jpg|- 1.html1.jpg2.jpg<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /&g…

如何使用python網絡爬蟲批量獲取公共資源數據技術

如何快速批量地獲取海量公共資源數據決定了科研的效率。Python網絡爬蟲是快速批量獲取網絡數據的重要手段&#xff0c;它按照發送請求、獲得頁面、解析頁面、下載內容、儲存內容等流程&#xff1f; 一&#xff1a;Python軟件的安裝及入門1 Python軟件安裝及入門1)Anaconda軟件安…

Kiro vs Cursor: AI IDE 終極對比指南

概述 隨著生成式 AI 革命性地改變了我們編寫代碼的方式&#xff0c;新一代 AI 驅動的集成開發環境 (IDE) 正在崛起。Kiro 和 Cursor 代表了這一運動的前沿&#xff0c;但它們采用了截然不同的方法。 核心理念對比 特性AWS KiroCursor核心理念結構化開發流程 (Spec-driven)對…

Python獲取網頁亂碼問題終極解決方案 | Python爬蟲編碼處理指南

在Python網絡爬蟲開發中&#xff0c;亂碼是最常見的問題之一。本文將深入探討亂碼產生的原因&#xff0c;并提供多種有效的解決方案&#xff0c;幫助您徹底解決Python獲取網頁內容時的亂碼問題。常見網頁編碼格式編碼類型使用場景Python解碼方式UTF-8現代網站標準編碼.decode(u…

Android MTK平臺預置多張靜態壁紙

執行 adb shell pm list package -f wallpaper 命令&#xff0c;查看壁紙應用路徑&#xff1a; /product/app/MtkWallpaperPicker/MtkWallpaperPicker.apkcom.android.wallpaperpicker 結果中帶 Mtk 就可確定MTK有對應用進行重構。其源碼路徑在 vendor/mediatek/proprietary/…

基于Django的個人博客系統開發(開題報告)

畢業論文(設計)開題報告論文(設計)題目 基于Django的個人博客系統開發 1.選題目的和意義 隨著云服務器的普及化以及編程培訓機構大量涌現,學習網站開發技術以及編程技術,通過租用個人云服務器部署代碼,構建個人博客網站,創建學習文檔,記錄學習過程,與他人交流技術學…

C++ 分配內存釋放內存

C 分配內存釋放內存一、new、delete、malloc和free最簡單的分配內存自定義對象分配和釋放內存二、new、delete與虛析構的問題三、一維、二維、多維數值創建和釋放一維二維多維四、new的缺點以及連續內存的優點一、new、delete、malloc和free 最簡單的分配內存 int* p_m (int*…

奧比中光深度相機開發

一、開發環境準備 1.1 硬件要求 奧比中光深度相機&#xff08;如Astra Pro、Gemini等&#xff09;USB 3.0接口&#xff08;確保數據傳輸穩定&#xff09;支持OpenGL的顯卡&#xff08;可選&#xff0c;用于點云可視化&#xff09; 1.2 軟件環境 SDK安裝&#xff1a; 從奧比…

標題 “Python 網絡爬蟲 —— selenium庫驅動瀏覽器

一、Selenium 庫核心認知 Selenium 庫是 Web 應用程序測試與自動化操作的利器 &#xff0c;能驅動瀏覽器&#xff08;如 Edge、Firefox 等&#xff09;執行點擊、輸入、打開、驗證等操作 。與 Requests 庫差異顯著&#xff1a;Requests 庫僅能獲取網頁原始代碼&#xff0c;而 …

從實踐出發--探究C/C++空類的大小,真的是1嗎?

文章目錄測試代碼VS2022正常運行編譯失敗GCC總結Author: NemaleSu Data: 2025/07/21 測試環境&#xff1a; Win11&#xff1a;VS2022Ubuntu22.04&#xff1a;gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0 相信眾多cpper聽過太多書籍、視頻、文檔、博客等資料&#xff0c;說C/C…

數據結構自學Day11-- 排序算法

一、排序算法的概念排序&#xff08;Sorting&#xff09;是指&#xff1a;將一組“無序”的數據&#xff0c;按照某種“順序規則”排列成“有序”的過程。1、按排序順序分類&#xff1a;升序&#xff1a;從小到大排列&#xff0c;如 1, 3, 5, 7, 9降序&#xff1a;從大到小排列…

電子元器件—三極管(一篇文章搞懂電路中的三極管)(筆記)(面試考試必備知識點)

三極管的定義及工作原理1. 定義三極管&#xff08;Transistor&#xff09;是一種具有三層半導體材料&#xff08;P-N-P 或 N-P-N&#xff09;構成的半導體器件&#xff0c;用于信號放大、開關控制和信號調制等應用。三極管有三個引腳&#xff1a;發射極&#xff08;Emitter&…

數據結構之克魯斯卡爾算法

前言&#xff1a;和Prim算法一樣&#xff0c;Kruskal 算法也是用來生成最小生成樹的&#xff0c;這篇文章來學習一下Kruskal算法的實現 一、實現流程 初始化的時候&#xff0c;將所有的邊用一個數組存儲&#xff0c;并且按權值從小到大進行排序&#xff0c;每次選一個權值最小的…

MongoDB 查詢時區問題

MongoDB默認時區是UTC&#xff0c;比北京時區晚八小時&#xff0c;北京時間UTC8h。 // 北京時間的 2024-10-01 08:00:00 // (>) 大于 - $gt // (<) 小于 - $lt // (>) 大于等于 - $gte // (< ) 小于等于 - $lte// Z代表UTC時區1、{"gmtCreate":{"$…

Windows VS2019 編譯 Apache Thrift 0.15.0

隨著微服務架構的普及,高效的跨語言遠程過程調用(RPC) 成為了構建分布式系統的重要基礎。Apache Thrift 是 Facebook 開源的一個輕量級、高性能的 RPC 框架,它允許開發者通過一個通用的接口定義語言(IDL)來定義服務接口和數據結構,并自動生成多種語言的客戶端和服務端代…

搭建種草商城框架指南

一、引言在當今電商市場&#xff0c;種草商城以其獨特的社交化購物模式受到越來越多用戶的喜愛。搭建一個功能完善、體驗良好的種草商城框架&#xff0c;需要綜合考慮前端界面、后端服務、數據庫設計等多個方面。本文將為你詳細介紹搭建種草商城框架的關鍵要點和技術選型。二、…

docker--掛載

設置容器的掛載 需要注意 掛載行為會覆蓋容器目標目錄的原有內容(未驗證)。 查看容器的掛載情況 在容器外部查看: docker inspect <容器名或容器ID> | grep -A n "Mounts" -A n 的含義 -A 是 --after-context 的縮寫,表示顯示匹配行及其后 n 行。 "Mo…

以Streamable HTTP方式訪問mcp server的過程

一、mcp server 部署 使用fastmcp框架 部署 mcp server&#xff0c; 以下是源代碼 # 引入 fastmcp 依賴包 from fastmcp import FastMCP# 新建fastmcp實例&#xff0c; 名字叫做 weather mcp FastMCP("weather")mcp.tool(name"weather", tags{"weath…