歸并排序 與 計數排序

目錄

1.歸并排序

1.1 遞歸實現歸并排序:

?1.2 非遞歸實現歸并排序

1.3 歸并排序的特性總結:

1.4 外部排序

2.計數排序

2.1 操作步驟:

2.2 計數排序的特性總結:

3. 7種常見比較排序比較


1.歸并排序

基本思想:

歸并排序(MERGE-SORT)是建立在歸并操作上的一種有效的排序算法,該算法是采用分治法(Divide andConquer)的一個非常典型的應用。已有序的子序列合并,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合并成一個有序表,稱為二路歸并。

歸并排序核心步驟:

?動圖演示:

1.1 遞歸實現歸并排序:

歸并排序類似于二叉樹中的后序遍歷,先讓整個數組分為兩個子序列,歸并這兩部份子序列,但是歸并需要兩部份子序列有序,然后取小的尾插到一個新開辟的數組中,歸并完成后后再拷貝回原數組,如何讓子序列有序,還要再次將每個子序列分為兩部分,直到每個子序列只有一個值,這時已經遞歸到最深處,然會遞歸向回歸并。

遞歸代碼實現:

//歸并排序
//開辟好空間后由下面元素調用此函數
void _MergeSort(int* arr, int* tmp, int begin, int end)
{if (begin == end){return;}int midi = (begin + end) / 2;_MergeSort(arr, tmp, begin, midi);_MergeSort(arr, tmp, midi+1, end);int begin1 = begin;int end1 = midi;int begin2 = midi + 1;int end2 = end;int i = begin;//歸并  取小的尾插到開辟的空間while (begin1 <= end1 && begin2 <= end2){if (arr[begin1] <= arr[begin2]){tmp[i++] = arr[begin1++];}else{tmp[i++] = arr[begin2++];}}while (begin1 <= end1){tmp[i++] = arr[begin1++];}while (begin2 <= end2){tmp[i++] = arr[begin2++];}//將歸并好的兩組數據拷貝會原數組memcpy(arr + begin, tmp + begin, sizeof(int) * (end - begin + 1));}void MergeSort(int* arr, int n)
{//開辟空間int* tmp = (int*)malloc(sizeof(int) * n);_MergeSort(arr, tmp, 0, n - 1);
}

小區間優化

//小區間優化
if (end - begin +1<10)
{//使用插入排序InsertSort(arr + begin, end - begin + 1);return;
}

優化的本質是減小遞歸調用的次數,由于二叉樹的性質。我們可以得出滿二叉樹后三層大約占總個數的85%。為了減小遞歸開銷,我們可以將小區間的遞歸調用改為直接插入排序可以提高一點排序的性能,但也不會提高很多。快排也可以使用這種方式優化。

?1.2 非遞歸實現歸并排序

我們可以先讓每組gap=1個數據,每次歸并兩組,然后在讓gap*=2,再次歸并,直到gap>n。

代碼實現:

//非遞歸實現歸并排序
void MergeSortNonR1(int* arr, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);//每組有gap個數據,歸并兩組int gap = 1;while (gap < n){int j = 0;for (int i = 0; i < n; i += 2 * gap){int begin1 = i, end1 = i + gap - 1;int begin2 = i + gap, end2 = i + 2 * gap - 1;if (end1 >= n || begin2 >= n)//不需要歸并{break;}//修正if (end2 >= n){end2 = n - 1;}//歸并while (begin1 <= end1 && begin2 <= end2){if (arr[begin1] <= arr[begin2]){tmp[j++] = arr[begin1++];}else{tmp[j++] = arr[begin2++];}}while (begin1 <= end1){tmp[j++] = arr[begin1++];}while (begin2 <= end2){tmp[j++] = arr[begin2++];}//將歸并后的兩組數據 拷貝回原數組 memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));}gap *= 2;}
}

邊界越界問題:

int begin1 = i, end1 = i + gap - 1;
int begin2 = i + gap, end2 = i + 2 * gap - 1;

begin1不會越界,因為begin1 = i,i 復合循環條件?。

  1. end1,begin2,end2都越界
  2. begin2,end2越界
  3. end2越界

1.?end1,begin2,end2都越界

???此時不需要歸并直接跳出循環。

2.?begin2,end2越界

?此時也不需要歸并直接跳出循環。

3.?end2越界

此時需要歸并,但是我們要修改end2,將end2改為n-1。

代碼:

if (end1 >= n || begin2 >= n)//不需要歸并{break;}//修正if (end2 >= n){end2 = n - 1;}

1.3 歸并排序的特性總結:

  1. 歸并的缺點在于需要O(N)的空間復雜度,歸并排序的思考更多的是解決在磁盤中的外排序問題。
  2. 時間復雜度:O(N*logN)
  3. 空間復雜度:O(N)
  4. 穩定性:穩定

1.4 外部排序

概念:當數據元素太多不能同時放在內存中,根據排序過程的要求不能在內外存之間移動數據的排序。

在我們所學的排序算法中,只有非遞歸歸并排序的思想可以用于外部排序。其他排序算法都只適用于內部排序,因為他們都使用了下標來進行隨機存取,而非遞歸歸并排序不需要,是順序存取,這里舉個例子:

假如我們由100億個整數要排序,也就是大約40G,而我們的內存中只有1G,步驟:

  1. 把40G的文件分為40份。
  2. 讓每份文件依次放到內部中排序,讓40份文件內部有序。
  3. 兩兩歸并,分別從兩個文件中讀一個數據,然后選小的寫文件,這時就與非遞歸歸并排序相同了。

2.計數排序

思想:計數排序又稱為鴿巢原理,是一種非比較排序,是對哈希直接定址法的變形應用。

2.1 操作步驟:

  1. 統計相同元素出現次數
  2. 根據統計的結果將序列回收到原來的序列中

?代碼實現:

// 計數排序
void CountSort(int* arr, int n)
{//遍歷 確定最大值與最小值int max = arr[0];int min = arr[0];for (int i = 0; i < n; i++){if (arr[i] < min){min = arr[i];}if (arr[i] > max){max = arr[i];}}//遍歷計數int range = max - min + 1;int* CountA = (int*)malloc(sizeof(int) * range);memset(CountA, 0, sizeof(int) * range);for (int i = 0; i < n; i++){CountA[arr[i] - min]++;}//回收到原數組int j = 0;for (int i = 0; i < range; i++){while (CountA[i]--){arr[j++] = i + min;}}
}

2.2 計數排序的特性總結:

  1. 計數排序在數據范圍集中時,效率很高,但是適用范圍及場景有限。
  2. 時間復雜度:O(MAX(N,范圍))
  3. 空間復雜度:O(范圍)
  4. 穩定性:穩定

3. 7種常見比較排序比較

排序方法平均情況最好情況最壞情況輔助空間穩定性
冒泡排序O(N^2)O(N)O(N^2)O(1)穩定
簡單選擇排序O(N^2)O(N^2)O(N^2)O(1)不穩定
直接插入排序O(N^2)O(N)O(N^2)O(1)穩定
希爾排序O(NlogN)~O(N^2)O(N^1.3)O(N^2)O(1)不穩定
堆排序O(NlogN)O(NlogN)O(N*logN)O(1)不穩定
歸并排序O(NlogN)O(NlogN)O(N*logN)O(n)穩定
快速排序O(NlogN)O(NlogN)O(N^2)O(logn)~O(n)不穩定

本篇結束!

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

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

相關文章

代理技術在網絡安全、爬蟲和數據隱私中的多重應用

1. Socks5代理&#xff1a;靈活的數據中轉 Socks5代理協議在網絡通信中起著關鍵作用。與其他代理技術不同&#xff0c;Socks5代理不僅支持TCP連接&#xff0c;還能夠處理UDP流量&#xff0c;使其在需要實時數據傳輸的場景中表現尤為出色。通過將請求和響應中轉到代理服務器&am…

redis分布式集群-redis+keepalived+ haproxy

redis分布式集群架構&#xff08;RedisKeepalivedHaproxy&#xff09;至少需要3臺服務器、6個節點&#xff0c;一臺服務器2個節點。 redis分布式集群架構中的每臺服務器都使用六個端口來實現多路復用&#xff0c;最終實現主從熱備、負載均衡、秒級切換的目標。 redis分布式集…

使用Edge和chrom擴展工具(GoFullPage)實現整頁面截圖或生成PDF文件

插件GoFullPage下載&#xff1a;點擊免費下載 如果在瀏覽網頁時&#xff0c;有需要整個頁面截圖或導出PDF文件的需求&#xff0c;這里分享一個Edge瀏覽器的擴展插件&#xff1a;GoFullPage。 這個工具可以一鍵實現頁面從上到下滾動并截取。 一、打開“管理擴展”&#xff08;…

網絡設備(防火墻、路由器、交換機)日志分析監控

外圍網絡設備&#xff08;如防火墻、路由器、交換機等&#xff09;是關鍵組件&#xff0c;因為它們控制進出公司網絡的流量。因此&#xff0c;監視這些設備的活動有助于 IT 管理員解決操作問題&#xff0c;并保護網絡免受攻擊者的攻擊。通過收集和分析這些設備的日志來監控這些…

Python 3 使用Hadoop 3之MapReduce總結

MapReduce 運行原理 MapReduce簡介 MapReduce是一種分布式計算模型&#xff0c;由Google提出&#xff0c;主要用于搜索領域&#xff0c;解決海量數據的計算問題。 MapReduce分成兩個部分&#xff1a;Map&#xff08;映射&#xff09;和Reduce&#xff08;歸納&#xff09;。…

tauri-react:快速開發跨平臺軟件的架子,支持自定義頭部和窗口陰影效果

tauri-react 一個使用 taurireacttsantd 開發跨平臺軟件的模板&#xff0c;支持窗口頭部自定義和窗口陰影&#xff0c;不用再自己做適配了&#xff0c;拿來即用&#xff0c;非常 nice。 開原地址&#xff1a;GitHub - Sjj1024/tauri-react: 一個最基礎的使用tauri和react開發…

生成式 AI 在泛娛樂行業的應用場景實踐 – 助力風格化視頻內容創作

感謝大家閱讀《生成式 AI 行業解決方案指南》系列博客&#xff0c;全系列分為 4 篇&#xff0c;將為大家系統地介紹生成式 AI 解決方案指南及其在電商、游戲、泛娛樂行業中的典型場景及應用實踐。目錄如下&#xff1a; 《生成式 AI 行業解決方案指南與部署指南》《生成式 AI 在…

一個概率論例題引發的思考

浙江大學版《概率論與數理統計》一書&#xff0c;第13章第1節例2&#xff1a; 這個解釋和模型比較簡單易懂。 接下來&#xff0c;第13章第2節的例2也跟此模型相關&#xff1a; 在我自己的理解中&#xff0c;此題的解法跟上一個題目一樣&#xff0c;其概率如下面的二維矩陣&a…

聊聊計算機技術

目錄 1.計算機的概念 2.計算機的發展過程 3.計算機的作用 4.計算機給人類帶來的福利 1.計算機的概念 計算機是一種用于處理和存儲數據的電子設備。它能夠執行各種操作&#xff0c;比如計算、邏輯操作、數據存儲和檢索等。計算機由硬件和軟件兩部分組成。 計算機的硬件包括中…

Go 語言并發編程 及 進階與依賴管理

1.0 從并發編程本質了解Go高性能的本質 1.1 Goroutine 協程可以理解為輕量級線程&#xff1b; Go更適合高并發場景原因之一&#xff1a;Go語言一次可以創建上萬協成&#xff1b; “快速”&#xff1a;開多個協成 打印。 go func(): 在函數前加 go 代表 創建協程; time.Sleep():…

基于深度信念網絡的西儲大學軸承故障分類識別,基于EMD+DBN的西儲大學軸承故障識別,LCD+DBN,LMD+DBN

目錄 背影 DBN神經網絡的原理 DBN神經網絡的定義 受限玻爾茲曼機(RBM) (EMD,LCD,LMD)+DBN的深度信念網絡的西儲大學軸承故障分類識別 基本結構 主要參數 數據 MATALB代碼 結果圖 展望 背影 DBN是一種深度學習神經網絡,擁有提取特征,非監督學習的能力,是一種非常好的分類…

Nacos使用SpringCloudAlibaba+Dubbo實現

Nacos簡介 Nacos是阿里的一個開源產品&#xff0c;它是針對微服務架構中的服務發現、服務治理、配置管理的綜合型解決方案。 官方介紹是這樣的&#xff1a; Nacos 致力于幫助您發現、配置和管理微服務。Nacos 提供了一組簡單易用的特性集&#xff0c;幫助您實現動態服務發現、…

CSDN編程題-每日一練(2023-08-14)

CSDN編程題-每日一練&#xff08;2023-08-14&#xff09; 一、題目名稱&#xff1a;小股炒股二、題目名稱&#xff1a;王子闖閘門三、題目名稱&#xff1a;圓小藝 一、題目名稱&#xff1a;小股炒股 時間限制&#xff1a;1000ms內存限制&#xff1a;256M 題目描述&#xff1a; …

Linux學習之防火墻概述

防火墻分類&#xff1a; 軟件防火墻&#xff1a;常用于數據包的過濾&#xff0c;比如限制某些ip或者端口&#xff0c;進行某些數據的轉發或者傳送 硬件防火墻&#xff1a;防御地域攻擊 軟件防火墻的分類&#xff1a; 包過濾防火墻&#xff1a;控制比較寬泛&#xff0c;防御效果…

ISIS技術(第三十七課)

1 分享一下華為官網上的一張地圖 官網地址:https://support.huawei.com/hedex/hdx.do?docid=EDOC1000105967&id=ZH-CN_CONCEPT_0000001501534705 2 路由的分類 -直連路由 直接連接的路由,且配置了IP地址之后(在同一網段內),就是直連路由。 -非直連路由 -靜態路由…

Shell命令之eval命令

1、基本作用 二次執行命令 2、基本格式 eval command-line3、例如 以下命令無法執行 pipe"|" ls $pipe wc -l ls: -l: No such file or directory ls: wc: No such file or directory ls: |: No such file or directory以下命令可以執行 eval ls $pipe wc -lSh…

Apache Dubbo概述

一、課程目標 1. 【了解】軟件架構的演進過程 2. 【理解】什么是RPC 3. 【掌握】Dubbo架構 4. 【理解】注冊中心Zookeeper 5. 【掌握】Zookeeper的安裝和使用 6. 【掌握】Dubbo入門程序 7. 【掌握】Dubbo管理控制臺的安裝和使用 8. 【理解】Dubbo配置二、分布式RPC框架Apache …

2021年06月 C/C++(二級)真題解析#中國電子學會#全國青少年軟件編程等級考試

第1題&#xff1a;數字放大 給定一個整數序列以及放大倍數x&#xff0c;將序列中每個整數放大x倍后輸出。 時間限制&#xff1a;1000 內存限制&#xff1a;65536 輸入 包含三行&#xff1a; 第一行為N&#xff0c;表示整數序列的長度(N ≤ 100); 第二行為N個整數(不超過整型范圍…

(css)點擊前隱藏icon圖表 點擊后顯示

(css)點擊前隱藏icon圖表 點擊后顯示 效果 html <liv-for"(item,index) in sessionList":key"index"class"liClass":class"{ active: change2 index }"tabindex"2">...<el-tooltip class"item" effec…

c++病毒/惡搞代碼大全( 下 )

注&#xff1a;以下代碼應勿用于非法&#xff08;Dev-c5.11實測可用&#xff09; 警告:以下為危險/永久性程序&#xff0c;請慎重使用 8. 效果:禁用任務管理器 提示:可能被殺毒軟件攔截 #include <stdio.h> #include <windows.h> int main() {HKEY hkey;DWORD …