數據結構|排序算法(三)選擇排序 堆排序 歸并排序

一、選擇排序

1.算法思想

選擇排序(Selection Sort)是一種簡單直觀的排序算法,其基本思想是:每次都從待排序部分中選出最小的一個數據和待排序的第一個數據交換。

將待排序序列分為已排序和未排序兩部分,初始時已排序部分為空,未排序部分包含整個待排序序列。在每一輪迭代中,從未排序部分中選擇最小(或最大)的元素,將其與未排序部分的第一個元素交換位置,從而將該元素添加到已排序部分的末尾。重復這個過程,直到整個序列都被排序。
選擇排序的具體步驟:
從整個序列中選擇最小的元素,將其與第一個位置的元素交換。此時,第一個位置的元素就是整個序列中最小的元素,已排序部分包含這一個元素,未排序部分包含剩余的元素。
在剩余的未排序元素中選擇最小的元素,將其與未排序部分的第一個位置(即第二個位置)的元素交換。此時,前兩個位置的元素是有序的,已排序部分包含兩個元素,未排序部分包含剩余的元素。
重復上述步驟,每次都從未排序部分中選擇最小的元素,并將其與未排序部分的第一個位置的元素交換,直到未排序部分只剩下一個元素。此時,整個序列已經完全有序。

2.代碼實現?

//選擇排序
void SelectSort(int* arr, int len)
{int tmp;int minIndex;//最小值的下標for (int i = 0; i < len - 1; i++){minIndex = i;for (int j = i + 1; j < len; j++){if (arr[minIndex] > arr[j]){minIndex = j;}}if (minIndex != i)//最小值和待排序的第一個為同一個,則不交換,提高效率{tmp = arr[minIndex];arr[minIndex] = arr[i];arr[i] = tmp;}}
}

?3.復雜度分析

1.選擇排序的時間復雜度為O(n2),其中n是待排序序列的長度。這是因為對于一個長度為n的序列,需要進行n?1輪選擇和交換操作,每輪操作需要遍歷未排序部分的元素,平均需要比較n/2次。

2.選擇排序的空間復雜度為O(1),因為它只需要使用常數級別的額外空間來進行元素的交換。

3. 不穩定:在選擇排序里,當把最小元素和未排序序列的首個元素交換時,可能會改變相等元素的相對順序。

二、堆排序

堆是一種特殊的完全二叉樹,分為大根堆和小根堆。

大根堆的每個節點的值都大于或等于其左右子節點的值,小根堆則相反,每個節點的值都小于或等于其左右子節點的值。(大根堆小根堆只看父子關系)


堆排序的基本思想是將待排序的序列構建成一個堆,然后依次取出堆頂元素并調整堆,直到整個序列有序。

1.算法思想

  • 建堆:將給定的數組構建成一個大根堆(或小根堆)。從最后一個非葉子節點開始,依次向上調整每個節點,使其滿足堆的性質。
  • 交換元素:將堆頂元素與堆的最后一個元素交換位置,此時堆頂元素是當前堆中的最大(或最小)值,將其取出,放到已排序序列的末尾。
  • 調整堆:交換元素后,堆的性質可能被破壞,需要對剩余的元素重新調整堆,使其再次滿足堆的性質。重復步驟 2 和 3,直到堆中只剩下一個元素,此時整個數組已經有序。

?1->調整成大根堆

(1)從最后一棵子樹開始,從后往前調整

(2)每次調整,從上往下

(3)整體調整成大根堆

具體調整:

定義一個臨時變量tmp,把根放到tmp里,找左右孩子的最大值,和tmp比較,如果比tmp大,則放到根的位置,繼續遞歸比較新的左右孩子的最大值

調整順序:

調整子樹:

?調整完成:

?2->根和待排序的最后一個交換

根是最大的,交換后則視作有序

3->再次調整成大根堆

2.代碼實現

//堆排序void HeapAdjust(int* arr, int start, int end)
{int tmp = arr[start];for (int i = 2 * start + 1; i <= end;i=2*i+1)//從上往下{if (i < end && arr[i] < arr[i + 1])//如果有右孩子,且左孩子的值小于右孩子{i++;}//i一定是左右孩子的最大值if (arr[i] > tmp){arr[start] = arr[i];start = i;}else{break;}}arr[start] = tmp;
}void HeapSort(int* arr, int len)
{//第一次建立大根堆(從后往前,多次調整)//根分別為4 3 2 1的子樹for (int i = (len-1-1)/2; i >= 0; i--)//i的初值與結點總數有關,i=總結點數len-根-{HeapAdjust(arr, i, len - 1);}//每次將根和待排序的最后一個交換,然后再次調整(注意是待排序部分)int tmp;//用于交換for (int i = 0; i < len - 1; i++){tmp = arr[0];arr[0] = arr[len - 1 - i];arr[len - 1 - i] = tmp;//再次調整HeapAdjust(arr, 0, len - 1 - i - 1);}return;
}

3.復雜度分析?

建立大根堆的時間復雜度:O(n)

每次調整大根堆時間復雜度:O(logn),調整次數n-1次,總時間復雜度O(nlogn)

綜合建堆和排序兩個階段,堆排序的時間復雜度為O(n+nlogn),通常簡化為O(nlogn)。這是堆排序的平均時間復雜度;

空間復雜度O(1);

不穩定

三、歸并排序

1.算法思想

歸并排序的基本思想是將一個數組分成兩個子數組,對每個子數組進行排序,然后將排序好的子數組合并成一個排序好的數組。這個過程是遞歸進行的,直到子數組的長度為 1,此時子數組已經是有序的。

1.分解:將待排序的數組不斷地分成兩半,直到每個子數組只有一個元素。可以使用遞歸實現這一步驟。
2.合并:將兩個已經排序好的子數組合并成一個排序好的數組。在合并過程中,比較兩個子數組的元素,將較小的元素依次放入一個臨時數組中,直到其中一個子數組的元素全部被放入臨時數組。然后將另一個子數組中剩余的元素全部放入臨時數組。最后將臨時數組中的元素復制回原數組。

注意邊界越界。?

2.代碼實現

//歸并排序
//一次歸并
//gap:歸并段的長度
static void Merge(int* arr, int len, int gap)
{int low1 = 0;//第一個歸并段的起始下標int high1 = low1 + gap - 1;//第一個歸并段的結束下標int low2 = high1 + 1;//第二個歸并段的起始下標int high2 = low2 + gap - 1 < len - 1 ? low2 + gap - 1 : len - 1;//第二個歸并段的結束下標//防止越界//存放歸并好的數據int* brr = (int*)malloc(len * sizeof(int));assert(brr != NULL);int i = 0;//brr的下標//有兩個歸并段while (low2 < len)//表面至少存在兩個歸并段{//兩個歸并段都有數據,需要比較low1和low2while (low1<=high1&&low2<=high2){if (arr[low1] <= arr[low2]){brr[i++] = arr[low1++];}else{brr[i++] = arr[low2++];}//誰小存誰}//一個歸并段的數據已經完成了,另一個還有數據while (low1 <= high1)//第一個歸并段還有數據{brr[i++] = arr[low1++];}while (low2 <= high2)//第二個歸并段還有數據{brr[i++] = arr[low2++];}//下兩個歸并段low1 = high2 + 1;high1 = low1 + gap - 1;low2 = high1 + 1;high2 = low2 + gap < len ? low2 + gap - 1 : len - 1;}//只有一個歸并段while (low1<len){brr[i++] = arr[low1++];}//將歸并好的數據拷貝到arr中for (i = 0; i < len; i++){arr[i] = brr[i];}free(brr);
}void MergeSort(int* arr, int len)
{for (int i = 1; i < len; i *= 2){Merge(arr, len, i);//一次歸并}
}

3.復雜度分析

歸并排序是一種基于分治思想的排序算法:

時間復雜度:
最好情況:當待排序序列已經是有序的時候,歸并排序依然需要進行logn層的歸并操作,每層歸并操作需要比較和移動n次元素,所以時間復雜度為O(nlogn)。
最壞情況:當待排序序列是逆序的時候,同樣需要logn層歸并操作,每層歸并操作也需要比較和移動n次元素,時間復雜度也是O(nlogn)。平均情況:歸并排序將序列分成兩部分,然后對兩部分分別排序,再將排好序的兩部分合并。

在平均情況下,每次劃分都能將序列分成大致相等的兩部分,所以時間復雜度為O(nlogn)。

空間復雜度:歸并排序在合并過程中需要借助額外的存儲空間來存放臨時數據,最壞情況下需要
O(n)的輔助空間來完成排序。

穩定性:歸并排序是穩定的排序算法。在歸并過程中,當左右兩個子序列中出現相等元素時,先將左邊子序列中的元素放入臨時數組,然后再將右邊子序列中的元素放入臨時數組,這樣相等元素的相對順序在排序前后不會發生改變。
綜上所述,歸并排序的時間復雜度為O(nlogn),空間復雜度為O(n),并且是穩定的排序算法。

以上是排序算法第三部分關于選擇排序、堆排序以及歸并排序的知識,如果有幫助可以點贊收藏一下,會持續更新輸出有用的內容,感興趣可以關注我!

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

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

相關文章

Vue3 + TypeScript,關于item[key]的報錯處理方法

處理方法1&#xff1a;// ts-ignore 注釋忽略報錯 處理方法2&#xff1a;item 設置為 any 類型

8.觀察者模式:思考與解讀

原文地址:觀察者模式&#xff1a;思考與解讀 更多內容請關注&#xff1a;7.深入思考與解讀設計模式 引言 在開發軟件時&#xff0c;系統的某些狀態可能會發生變化&#xff0c;而你希望這些變化能夠自動通知到依賴它們的其他模塊。你是否曾經遇到過&#xff0c;系統中某個對象…

【HD-RK3576-PI】Ubuntu桌面多顯、旋轉以及更新Logo

硬件&#xff1a;HD-RK3576-PI 軟件&#xff1a;Linux6.1Ubuntu22.04 在基于HD-RK3576-PI硬件平臺運行Ubuntu 22系統的開發過程中&#xff0c;屏幕方向調整是提升人機交互體驗的關鍵環節。然而&#xff0c;由于涉及uboot引導階段、內核啟動界面、桌面環境顯示全流程適配&#x…

Rsync+sersync2實現目錄實時同步

Sersync rsync 實現實時同步服務 sersync2二進制包目錄規劃 /app/tools/sersync/ /app/tools/sersync/bin /app/tools/sersync/conf項目架構是這樣的&#xff1a; ------------------- ------------------- ------------------- | | …

MySQL視圖高級應用與最佳實踐

1. 視圖與索引的協同優化?? ??物化視圖&#xff08;模擬實現&#xff09;?? MySQL原生不支持物化視圖&#xff0c;但可通過“定時刷新”的物理表模擬&#xff1a; -- 1. 創建存儲結果的物理表 CREATE TABLE cached_monthly_sales (product_id INT,total_sales DECIMAL(10…

string的模擬實現 (6)

目錄 1.string.h 2.string.cpp 3.test.cpp 4.一些注意點 本篇博客就學習下如何模擬實現簡易版的string類&#xff0c;學好string類后面學習其他容器也會更輕松些。 代碼實現如下&#xff1a; 1.string.h #define _CRT_SECURE_NO_WARNINGS 1 #pragma once #include <…

Unity:像素(Pixels) 和 單位(Units)

目錄 從第一性原理出發&#xff1a;什么是像素和 Unit&#xff1f; &#x1f9f1; 1. 像素&#xff08;Pixel&#xff09;&#xff1a;圖像的最小單位 &#x1f4d0; 2. Unity Unit&#xff08;單位&#xff09;&#xff1a;游戲世界中的度量單位 核心換算公式&#xff1a;…

【失敗總結】Win10系統安裝docker

1.啟用或關閉windows功能中&#xff0c;將Hyper-V功能勾選全部啟用&#xff0c;容器勾選。設置好后要重啟電腦。 2.管網下載下載安裝Docker  Docker官網&#xff1a;https://www.docker.com/ 3.可以自定義Docker安裝路徑 新建安裝目錄&#xff1a;d:\MySoftware\Docker并將D…

《Adaptive Layer-skipping in Pre-trained LLMs》- 論文筆記

作者&#xff1a;Xuan Luo, Weizhi Wang, Xifeng Yan Department of Computer Science, UC Santa Barbara xuan_luoucsb.edu, weizhiwangucsb.edu, xyancs.ucsb.edu 1. 引言與動機 1.1 背景 LLM 的成功與挑戰: 大型語言模型 (LLMs) 在翻譯、代碼生成、推理等任務上取得巨大成…

DQN在Gym的MountainCar環境的實現

DQN on MountainCar 引言 在本次實驗里&#xff0c;我構建了DQN和Dueling DQN&#xff0c;并在Gymnasium庫的MountainCar環境中對它們展開測試。我通過調整訓練任務的超參數&#xff0c;同時設計不同的獎勵函數及其對應參數&#xff0c;致力于獲取更優的訓練效果。最后&#…

計算機網絡綜合實驗指南

計算機網絡綜合實驗指南 本實驗將結合《計算機網絡自頂向下》前三章的核心概念&#xff0c;通過實際操作加深對應用層、運輸層和網絡層的理解。實驗涵蓋 HTTP/TCP抓包分析、DNS解析觀察、網頁性能評估及簡單Socket編程&#xff0c;幫助你將理論轉化為實踐。 實驗準備 工具&…

【AI部署】騰訊云GPU-RUN—SadTalker的AI數字人視頻—未來之窗超算中心

磁盤空間 創建未來之窗 查看磁盤命令 df -h 指定路徑創建環境 conda create --prefix sadtalker python3.10 指令路徑運行環境 conda activate ./sadtalker 安裝環境 pip install torch1.12.1cu113 torchvision0.13.1cu113 torchaudio0.12.1 --extra-index-url https://…

爬蟲利器SpiderTools谷歌插件教程v1.0.0!!!web端JavaScript環境檢測!!!

SpiderTools谷歌插件教程v1.0.0 一、SpiderTools簡介二、下載通道三、插件介紹四、插件使用五、工具函數使用 補環境工具推薦&#xff1a;爬蟲補環境利器webEnv 一、SpiderTools簡介 SpiderTools主要用于檢測和監控網頁的JavaScript運行環境。該插件可以幫助開發者更好地查看…

Android開發協調布局滑動懸停

Android開發協調布局滑動懸停 直接給個xml,防止下次忘了怎么寫。 <?xml version="1.0" encoding="utf-8"?> <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"x…

Linux學習——TCP

一.TCP編程API 1.socket函數 1.socket函數 include include int socket(int domain,int type,int protocol); 參數 domain AF_INET AF_INET6 AF_UNIX,AF_LOCAL AF_NETLINK AF_PACKET type SOCK_STREAM: 流式…

Linux驅動開發--異步通知與異步I/O

3、異步通知與異步I/O 3.1 Linux信號 阻塞與非阻塞訪問、poll()函數提供了較好的解決設備訪問的機制&#xff0c;但是如果有了異步通知&#xff0c;整套機制則更加完整了。 異步通知的意思是&#xff1a;一旦設備就緒&#xff0c;則主動通知應用程序&#xff0c;這樣應用程序…

大語言模型推理能力的強化學習現狀理解GRPO與近期推理模型研究的新見解

每周跟蹤AI熱點新聞動向和震撼發展 想要探索生成式人工智能的前沿進展嗎&#xff1f;訂閱我們的簡報&#xff0c;深入解析最新的技術突破、實際應用案例和未來的趨勢。與全球數同行一同&#xff0c;從行業內部的深度分析和實用指南中受益。不要錯過這個機會&#xff0c;成為AI領…

【Linux系統】Linux基礎指令(詳解Linux命令行常用指令,每一個指令都有示例演示)

文章目錄 一、與文件路徑相關的指令0.補充知識&#xff1a;路徑的認識1.pwd 指令2.cd 指令&#xff08;含家目錄的介紹&#xff09; 二、創建和刪除文件的指令0.補充知識&#xff1a;普通文件和目錄文件1.touch 指令&#xff08;可以修改文件的時間戳&#xff09;2.mkdir 指令3…

LangChain 單智能體模式示例【純代碼】

# LangChain 單智能體模式示例import os from typing import Anyfrom langchain.agents import AgentType, initialize_agent, Tool from langchain_openai import ChatOpenAI from langchain.tools import BaseTool from langchain_experimental.tools.python.tool import Pyt…

解決:VSCode C++ conan 安裝第三方庫后 頭文件報錯

文章目錄 1 頭文件include路徑查找報錯參考 1 頭文件include路徑查找報錯 找到conan_toolchain.cmake中 INCLUDE_PATH list(PREPEND CMAKE_INCLUDE_PATH "/Users/hanliqiang/.conan2/p/b/fmte8c4f7a755477/p/include")生成C編譯配置 CtrlShiftP 中選擇C Edit Confi…