日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

冒泡排序c++代码_八大排序算法(解释+代码+结果+算法优化)

發(fā)布時(shí)間:2025/4/5 c/c++ 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 冒泡排序c++代码_八大排序算法(解释+代码+结果+算法优化) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

》》》歡迎點(diǎn)贊,收藏,轉(zhuǎn)發(fā)! 評(píng)論區(qū)獲取源代碼與更多更全干貨!《《《

排序算法可以分為內(nèi)部排序和外部排序,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序,不需要訪問(wèn)外存便能完成. 而外部排序是因排序的數(shù)據(jù)很大,一次不能容納全部的排序記錄,在排序過(guò)程中需要訪問(wèn)外存。常見(jiàn)的內(nèi)部排序算法有:插入排序、希爾排序、選擇排序、冒泡排序、歸并排序、快速排序、堆排序、基數(shù)排序等。用一張圖概括:

外部排序點(diǎn)擊以下圖片查看大圖:

關(guān)于時(shí)間復(fù)雜度

平方階 (O(n2)) 排序 各類(lèi)簡(jiǎn)單排序:直接插入、直接選擇和冒泡排序。

線性對(duì)數(shù)階 (O(nlog2n)) 排序 快速排序、堆排序和歸并排序;

O(n1+§)) 排序,§ 是介于 0 和 1 之間的常數(shù)。 希爾排序

線性階 (O(n)) 排序 基數(shù)排序,此外還有桶、箱排序。

關(guān)于穩(wěn)定性

穩(wěn)定的排序算法:冒泡排序、插入排序、歸并排序和基數(shù)排序。

不是穩(wěn)定的排序算法:選擇排序、快速排序、希爾排序、堆排序。

名詞解釋:

n:數(shù)據(jù)規(guī)模

k:"桶"的個(gè)數(shù)

In-place:占用常數(shù)內(nèi)存,不占用額外內(nèi)存

Out-place:占用額外內(nèi)存

穩(wěn)定性:排序后 2 個(gè)相等鍵值的順序和排序之前它們的順序相同

1. 冒泡排序 BubbleSort

冒泡排序是一種交換排序。

什么是交換排序呢?

—— 兩兩比較待排序的關(guān)鍵字,并交換不滿足次序要求的那對(duì)數(shù),直到整個(gè)表都滿足次序要求為止。

它重復(fù)地走訪要排序的數(shù)列,一次比較兩個(gè)元素,如果他們的順序錯(cuò)誤就把他們交換過(guò)來(lái)。走訪數(shù)列的工作是重復(fù)地進(jìn)行直到?jīng)]有再需要交換,也就是說(shuō)該數(shù)列已經(jīng)排序完成。

這個(gè)算法的名字由來(lái)是因?yàn)樵叫〉脑貢?huì)經(jīng)由交換慢慢“浮”到數(shù)列的頂端,故名冒泡排序。

動(dòng)態(tài)效果示意圖:

假設(shè)有一個(gè)大小為 N 的無(wú)序序列。以升序冒泡排序?yàn)槔?#xff0c;冒泡排序就是要每趟排序過(guò)程中通過(guò)兩兩比較相鄰元素,將小的數(shù)字放到前面,大的數(shù)字放在后面。

算法分析

1、冒泡排序算法的性能

2、時(shí)間復(fù)雜度

若文件的初始狀態(tài)是正序的,一趟掃描即可完成排序。所需的關(guān)鍵字比較次數(shù)C和記錄移動(dòng)次數(shù)M均達(dá)到最小值:Cmin = N - 1, Mmin = 0。所以,冒泡排序最好時(shí)間復(fù)雜度為O(N)。

但是上述代碼,不能掃描一趟就完成排序,它會(huì)進(jìn)行全掃描。所以一個(gè)改進(jìn)的方法就是,當(dāng)冒泡中途發(fā)現(xiàn)已經(jīng)為正序了,便無(wú)需繼續(xù)比對(duì)下去。改進(jìn)方法一會(huì)兒介紹。

若初始文件是反序的,需要進(jìn)行 N -1 趟排序。每趟排序要進(jìn)行 N - i 次關(guān)鍵字的比較(1 ≤ i ≤ N - 1),且每次比較都必須移動(dòng)記錄三次來(lái)達(dá)到交換記錄位置。在這種情況下,比較和移動(dòng)次數(shù)均達(dá)到最大值:

Cmax = N(N-1)/2 = O(N^2)

Mmax = 3N(N-1)/2 = O(N^2)

冒泡排序的最壞時(shí)間復(fù)雜度為O(N^2)。

因此,冒泡排序的平均時(shí)間復(fù)雜度為O(N^2)。

總結(jié)起來(lái),其實(shí)就是一句話:當(dāng)數(shù)據(jù)越接近正序時(shí),冒泡排序性能越好。

3. 算法穩(wěn)定性

假定在待排序的記錄序列中,存在多個(gè)具有相同的關(guān)鍵字的記錄,若經(jīng)過(guò)排序,這些記錄的相對(duì)次序保持不變,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,則稱這種排序算法是穩(wěn)定的;否則稱為不穩(wěn)定的。

冒泡排序就是把小的元素往前調(diào)或者把大的元素往后調(diào)。是相鄰的兩個(gè)元素的比較,交換也發(fā)生在這兩個(gè)元素之間。所以相同元素的前后順序并沒(méi)有改變,所以冒泡排序是一種穩(wěn)定排序算法。

4. 優(yōu)化

對(duì)冒泡排序常見(jiàn)的改進(jìn)方法是加入標(biāo)志性變量exchange,用于標(biāo)志某一趟排序過(guò)程中是否有數(shù)據(jù)交換。

如果進(jìn)行某一趟排序時(shí)并沒(méi)有進(jìn)行數(shù)據(jù)交換,則說(shuō)明所有數(shù)據(jù)已經(jīng)有序,可立即結(jié)束排序,避免不必要的比較過(guò)程。

2. 快速排序 Quicksort

快速排序是一種交換排序,它由C. A. R. Hoare在1962年提出。快速排序(quick sort)的采用了分而治之(divide and conquer)的策略:將原問(wèn)題分解為若干個(gè)規(guī)模更小但結(jié)構(gòu)與原問(wèn)題相似的子問(wèn)題。遞歸地解這些子問(wèn)題,然后將這些子問(wèn)題的解組合為原問(wèn)題的解。

1. 算法思想

快速排序的基本思想是:通過(guò)一趟排序?qū)⒁判虻臄?shù)據(jù)分割成獨(dú)立的兩部分:分割點(diǎn)左邊都是比它小的數(shù),右邊都是比它大的數(shù)。

然后再按此方法對(duì)這兩部分?jǐn)?shù)據(jù)分別進(jìn)行快速排序,整個(gè)排序過(guò)程可以遞歸進(jìn)行,以此達(dá)到整個(gè)數(shù)據(jù)變成有序序列。

動(dòng)態(tài)效果示意圖:

詳細(xì)的圖解往往比大堆的文字更有說(shuō)明力,所以直接上圖:

上圖中,演示了快速排序的處理過(guò)程:

初始狀態(tài)為一組無(wú)序的數(shù)組:2、4、5、1、3。

經(jīng)過(guò)以上操作步驟后,完成了第一次的排序,得到新的數(shù)組:1、2、5、4、3。

新的數(shù)組中,以2為分割點(diǎn),左邊都是比2小的數(shù),右邊都是比2大的數(shù)。

因?yàn)?已經(jīng)在數(shù)組中找到了合適的位置,所以不用再動(dòng)。

2左邊的數(shù)組只有一個(gè)元素1,所以顯然不用再排序,位置也被確定。(注:這種情況時(shí),left指針和right指針顯然是重合的。因此在代碼中,我們可以通過(guò)設(shè)置判定條件left必須小于right,如果不滿足,則不用不用不用不不用不用不用不用不用用不用排序了)。

而對(duì)于2右邊的數(shù)組5、4、3,設(shè)置left指向5,right指向3,開(kāi)始繼續(xù)重復(fù)圖中的一、二、三、四步驟,對(duì)新的數(shù)組進(jìn)行排序。

快排的工作過(guò)程其實(shí)比較簡(jiǎn)單,三步走:

a. 選擇基準(zhǔn)值 pivot 將數(shù)組分成兩個(gè)子數(shù)組:小于基準(zhǔn)值的元素和大于基準(zhǔn)值的元素。這個(gè)過(guò)程稱之為 partition

b. 對(duì)這兩個(gè)子數(shù)組進(jìn)行快速排序。

c. 合并結(jié)果,遞歸地(recursive)把小于基準(zhǔn)值元素的子數(shù)列和大于基準(zhǔn)值元素的子數(shù)列排序。

2. 代碼+結(jié)果

3. 算法分析

3.1 快速排序算法的性能

3.2 時(shí)間復(fù)雜度

當(dāng)數(shù)據(jù)有序時(shí),以第一個(gè)關(guān)鍵字為基準(zhǔn)分為兩個(gè)子序列,前一個(gè)子序列為空,此時(shí)執(zhí)行效率最差。

而當(dāng)數(shù)據(jù)隨機(jī)分布時(shí),以第一個(gè)關(guān)鍵字為基準(zhǔn)分為兩個(gè)子序列,兩個(gè)子序列的元素個(gè)數(shù)接近相等,此時(shí)執(zhí)行效率最好。

所以,數(shù)據(jù)越隨機(jī)分布時(shí),快速排序性能越好;數(shù)據(jù)越接近有序,快速排序性能越差。

3.3 時(shí)間復(fù)雜度

快速排序在每次分割的過(guò)程中,需要 1 個(gè)空間存儲(chǔ)基準(zhǔn)值。而快速排序的大概需要 logN次的分割處理,所以占用空間也是 logN 個(gè)。

3.4 算法穩(wěn)定性

在快速排序中,相等元素可能會(huì)因?yàn)榉謪^(qū)而交換順序,所以它是不穩(wěn)定的算法。

3. 直接插入排序 Straight Insertion Sort

直接插入排序(Insertion Sort)序是一種最簡(jiǎn)單的插入排序。為簡(jiǎn)化問(wèn)題,我們下面只討論升序排序。

1. 算法思想

插入排序:每一趟將一個(gè)待排序的記錄,按照其關(guān)鍵字的大小插入到有序隊(duì)列的合適位置里,知道全部插入完成。

動(dòng)態(tài)效果示意圖:

以上的過(guò)程,其實(shí)就是典型的直接插入排序,每次將一個(gè)新數(shù)據(jù)插入到有序隊(duì)列中的合適位置里。

很簡(jiǎn)單吧,接下來(lái),我們要將這個(gè)算法轉(zhuǎn)化為編程語(yǔ)言。

假設(shè)有一組無(wú)序序列 R0, R1, ... , RN-1。

(1) 我們先將這個(gè)序列中下標(biāo)為 0 的元素視為元素個(gè)數(shù)為 1 的有序序列。

(2) 然后,我們要依次把 R1, R2, ... , RN-1 插入到這個(gè)有序序列中。所以,我們需要一個(gè)外部循環(huán),從下標(biāo) 1 掃描到 N-1 。

(3) 接下來(lái)描述插入過(guò)程。假設(shè)這是要將 Ri 插入到前面有序的序列中。由前面所述,我們可知,插入Ri時(shí),前 i-1 個(gè)數(shù)肯定已經(jīng)是有序了。

所以我們需要將Ri 和R0 ~ Ri-1 進(jìn)行比較,確定要插入的合適位置。這就需要一個(gè)內(nèi)部循環(huán),我們一般是從后往前比較,即從下標(biāo) i-1 開(kāi)始向 0 進(jìn)行掃描。

2. 代碼+答案

3. 算法分析

3.1 直接插入排序的算法性能

3.2 時(shí)間復(fù)雜度

當(dāng)數(shù)據(jù)正序時(shí),執(zhí)行效率最好,每次插入都不用移動(dòng)前面的元素,時(shí)間復(fù)雜度為O(N)。

當(dāng)數(shù)據(jù)反序時(shí),執(zhí)行效率最差,每次插入都要前面的元素后移,時(shí)間復(fù)雜度為O(N^2)。

所以,數(shù)據(jù)越接近正序,直接插入排序的算法性能越好。

3.3 空間復(fù)雜度

由直接插入排序算法可知,我們?cè)谂判蜻^(guò)程中,需要一個(gè)臨時(shí)變量存儲(chǔ)要插入的值,所以空間復(fù)雜度為 1 。

3.4 算法穩(wěn)定性

直接插入排序的過(guò)程中,不需要改變相等數(shù)值元素的位置,所以它是穩(wěn)定的算法。

4. 優(yōu)化

因?yàn)樵谝粋€(gè)有序序列中查找一個(gè)插入位置,以保證有序序列的序列不變,所以可以使用二分查找,減少元素比較次數(shù)提高效率。

二分查找是對(duì)于有序數(shù)組而言的,假設(shè)如果數(shù)組是升序排序的。那么,二分查找算法就是不斷對(duì)數(shù)組進(jìn)行對(duì)半分割,每次拿中間元素和目標(biāo)數(shù)字進(jìn)行比較,如果中間元素小于目標(biāo)數(shù)字,則說(shuō)明目標(biāo)數(shù)字應(yīng)該在右側(cè)被分割的數(shù)組中,如果中間元素大于目標(biāo)數(shù)字,則說(shuō)明目標(biāo)數(shù)字應(yīng)該在左側(cè)被分割的數(shù)組中。

4. 希爾排序 Shell's Sort

希爾(Shell)排序又稱為縮小增量排序,它是一種插入排序。它是直接插入排序算法的一種威力加強(qiáng)版。

希爾排序,也稱遞減增量排序算法,以其設(shè)計(jì)者希爾(Donald Shell)的名字命名,該算法由 1959 年公布。

1. 算法思想

我們舉個(gè)例子來(lái)描述算法流程(以下摘自維基百科):

假設(shè)有這樣一組數(shù) {13, 14, 94, 33, 82, 25, 59, 94, 65, 23, 45, 27, 73, 25, 39, 10},如果我們以步長(zhǎng)為 5 開(kāi)始進(jìn)行排序:

13 14 94 33 82

25 59 94 65 23

45 27 73 25 39

10

然后我們對(duì)每列進(jìn)行排序:

10 14 73 25 23

13 27 94 33 39

25 59 94 65 82

45

將上述四行數(shù)字,依序接在一起時(shí)我們得到:{10, 14, 73, 25, 23, 13, 27, 94, 33, 39, 25, 59, 94, 65, 82, 45},然后再以 3 為步長(zhǎng):

10 14 73

25 23 13

27 94 33

39 25 59

94 65 82

45

排序之后變?yōu)?#xff1a;

10 14 13

25 23 33

27 25 59

39 65 73

45 94 82

94

最后以 1 為步長(zhǎng)進(jìn)行排序(此時(shí)就是簡(jiǎn)單的插入排序了)。

可想而知,步長(zhǎng)的選擇是希爾排序的重要部分。算法最開(kāi)始以一定的步長(zhǎng)進(jìn)行排序,然后會(huì)繼續(xù)以更小的步長(zhǎng)進(jìn)行排序,最終算法以步長(zhǎng)為 1 進(jìn)行排序。當(dāng)步長(zhǎng)為 1 時(shí),算法變?yōu)橹苯硬迦肱判?#xff0c;這就保證了數(shù)據(jù)一定會(huì)被全部排序。

下面以n/2作為步長(zhǎng)為例進(jìn)行講解。(步長(zhǎng)自己取)

算法分析

希爾排序的算法性能

1. 時(shí)間復(fù)雜度

步長(zhǎng)的選擇是希爾排序的重要部分,只要最終步長(zhǎng)為1任何步長(zhǎng)序列都可以工作。

算法最開(kāi)始以一定的步長(zhǎng)進(jìn)行排序。然后會(huì)繼續(xù)以一定步長(zhǎng)進(jìn)行排序,最終算法以步長(zhǎng)為1進(jìn)行排序。當(dāng)步長(zhǎng)為1時(shí),算法變?yōu)椴迦肱判?#xff0c;這就保證了數(shù)據(jù)一定會(huì)被排序。

步長(zhǎng)序列的不同,會(huì)導(dǎo)致最壞的時(shí)間復(fù)雜度情況的不同。

本文中,以N/2為步長(zhǎng)的最壞時(shí)間復(fù)雜度為N^2。

Donald Shell 最初建議步長(zhǎng)選擇為N/2并且對(duì)步長(zhǎng)取半直到步長(zhǎng)達(dá)到1。雖然這樣取可以比O(N^2)類(lèi)的算法(插入排序)更好,但這樣仍然有減少平均時(shí)間和最差時(shí)間的余地。可能希爾排序最重要的地方在于當(dāng)用較小步長(zhǎng)排序后,以前用的較大步長(zhǎng)仍然是有序的。比如,如果一個(gè)數(shù)列以步長(zhǎng)5進(jìn)行了排序然后再以步長(zhǎng)3進(jìn)行排序,那么該數(shù)列不僅是以步長(zhǎng)3有序,而且是以步長(zhǎng)5有序。如果不是這樣,那么算法在迭代過(guò)程中會(huì)打亂以前的順序,那就不會(huì)以如此短的時(shí)間完成排序了。

用這樣步長(zhǎng)序列的希爾排序比插入排序要快,甚至在小數(shù)組中比快速排序和堆排序還快,但是在涉及大量數(shù)據(jù)時(shí)希爾排序還是比快速排序慢。

2. 算法穩(wěn)定性

希爾排序中相等數(shù)據(jù)可能會(huì)交換位置,所以希爾排序是不穩(wěn)定的算法。

3. 直接插入排序和希爾排序的比較

直接插入排序是穩(wěn)定的;而希爾排序是不穩(wěn)定的。

直接插入排序更適合于原始記錄基本有序的集合。

希爾排序的比較次數(shù)和移動(dòng)次數(shù)都要比直接插入排序少,當(dāng)N越大時(shí),效果越明顯。

希爾排序的比較次數(shù)和移動(dòng)次數(shù)都要比直接插入排序少,當(dāng)N越大時(shí),效果越明顯。

直接插入排序也適用于鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu);希爾排序不適用于鏈?zhǔn)浇Y(jié)構(gòu)。

5. 簡(jiǎn)單選擇排序

簡(jiǎn)單選擇排序是一種選擇排序。

選擇排序:每趟從待排序的記錄中選出關(guān)鍵字最小的記錄,順序放在已排序的記錄序列末尾,直到全部排序結(jié)束為止。

1. 算法思想

簡(jiǎn)單排序很簡(jiǎn)單,它的大致處理流程為:

從待排序序列中,找到關(guān)鍵字最小的元素;

如果最小元素不是待排序序列的第一個(gè)元素,將其和第一個(gè)元素互換;

從余下的 N - 1 個(gè)元素中,找出關(guān)鍵字最小的元素,重復(fù)(1)、(2)步,直到排序結(jié)束。

動(dòng)態(tài)效果示意圖:

舉例說(shuō)明,處理過(guò)程示意圖如下所示:

如圖所示,每趟排序中,將當(dāng)前第 i 小的元素放在位置 i 上。

2. 代碼+結(jié)果

3. 算法分析

3.1 簡(jiǎn)單算法排序性能

其中,N2為N^2。

3.2 時(shí)間復(fù)雜度

簡(jiǎn)單選擇排序的比較次數(shù)與序列的初始排序無(wú)關(guān)。 假設(shè)待排序的序列有 N 個(gè)元素,則比較次數(shù)總是N (N - 1) / 2。

而移動(dòng)次數(shù)與序列的初始排序有關(guān)。當(dāng)序列正序時(shí),移動(dòng)次數(shù)最少,為 0.

當(dāng)序列反序時(shí),移動(dòng)次數(shù)最多,為3N (N - 1) / 2。

所以,綜合以上,簡(jiǎn)單排序的時(shí)間復(fù)雜度為O(N^2)。

3.3 空間復(fù)雜度

簡(jiǎn)單選擇排序需要占用1個(gè)臨時(shí)空間,用于保存最小值得索引。

6. 堆排序

堆排序是一種選擇排序。

選擇排序:每趟從待排序的記錄中選出關(guān)鍵字最小的記錄,順序放在已排序的記錄序列末尾,直到全部排序結(jié)束為止。

1. 算法思想

堆排序是利用堆的性質(zhì)進(jìn)行的一種選擇排序。

動(dòng)態(tài)效果示意圖:

堆是一棵順序存儲(chǔ)的完全二叉樹(shù)。

其中每個(gè)結(jié)點(diǎn)的關(guān)鍵字都不大于其孩子結(jié)點(diǎn)的關(guān)鍵字,這樣的堆稱為小根堆。

其中每個(gè)結(jié)點(diǎn)的關(guān)鍵字都不小于其孩子結(jié)點(diǎn)的關(guān)鍵字,這樣的堆稱為大根堆。

舉例來(lái)說(shuō),對(duì)于n個(gè)元素的序列{R0, R1, ... , Rn}當(dāng)且僅當(dāng)滿足下列關(guān)系之一時(shí),稱之為堆:

Ri <= R2i+1 且 Ri <= R2i+2 (小根堆)

Ri >= R2i+1 且 Ri >= R2i+2 (大根堆)

其中i=1,2,…,n/2向下取整;

如上圖所示,序列R{3, 8, 15, 31, 25}是一個(gè)典型的小根堆。

堆中有兩個(gè)結(jié)點(diǎn),元素3和元素8。

元素3在數(shù)組中以R[0]表示,它的左孩子結(jié)點(diǎn)是R[1],右孩子結(jié)點(diǎn)是R[2]。

元素8在數(shù)組中以R[1]表示,它的左孩子結(jié)點(diǎn)是R[3],右孩子結(jié)點(diǎn)是R[4],它的父結(jié)點(diǎn)是R[0]。可以看出,它們滿足以下規(guī)律:

設(shè)當(dāng)前元素在數(shù)組中以R[i]表示,那么,

(1) 它的左孩子結(jié)點(diǎn)是:R[2*i+1];

(2) 它的右孩子結(jié)點(diǎn)是:R[2*i+2];

(3) 它的父結(jié)點(diǎn)是:R[(i-1)/2];

(4) R[i] <= R[2*i+1] 且 R[i] <= R[2i+2]。

首先,按堆的定義將數(shù)組R[0..n]調(diào)整為堆(這個(gè)過(guò)程稱為創(chuàng)建初始堆),交換R[0]和R[n];

然后,將R[0..n-1]調(diào)整為堆,交換R[0]和R[n-1];

如此反復(fù),直到交換了R[0]和R[1]為止。

以上思想可歸納為兩個(gè)操作:

(1)根據(jù)初始數(shù)組去構(gòu)造初始堆(構(gòu)建一個(gè)完全二叉樹(shù),保證所有的父結(jié)點(diǎn)都比它的孩子結(jié)點(diǎn)數(shù)值大)。

(2)每次交換第一個(gè)和最后一個(gè)元素,輸出最后一個(gè)元素(最大值),然后把剩下元素重新調(diào)整為大根堆。

當(dāng)輸出完最后一個(gè)元素后,這個(gè)數(shù)組已經(jīng)是按照從小到大的順序排列了。

先通過(guò)詳細(xì)的實(shí)例圖來(lái)看一下,如何構(gòu)建初始堆。

設(shè)有一個(gè)無(wú)序序列 { 1, 3, 4, 5, 2, 6, 9, 7, 8, 0 }。

構(gòu)造了初始堆后,我們來(lái)看一下完整的堆排序處理:

還是針對(duì)前面提到的無(wú)序序列 { 1, 3, 4, 5, 2, 6, 9, 7, 8, 0 } 來(lái)加以說(shuō)明。

比如如下數(shù)組 {57, 40, 38, 11, 13, 34, 48, 75, 6, 19, 9, 7}堆排序前如下:

進(jìn)行堆排序后如下:

最大堆的存儲(chǔ)結(jié)構(gòu)如下:

接著,最后一步,堆排序,進(jìn)行(n-1)次循環(huán)。

相信,通過(guò)以上兩幅圖,應(yīng)該能很直觀的演示堆排序的操作處理。

看完上面所述的流程你至少有一個(gè)疑問(wèn):

如何確定最后一個(gè)非葉子結(jié)點(diǎn)?

其實(shí)這是有一個(gè)公式的,設(shè)二叉樹(shù)結(jié)點(diǎn)總數(shù)為 n,則最后一個(gè)非葉子結(jié)點(diǎn)是第?n/2?個(gè)。

2. 代碼+結(jié)果:

3. 算法分析

3.1 堆排序算法的總體情況

3.2 時(shí)間復(fù)雜度

首先計(jì)算建堆的時(shí)間,也就是下面的代碼,

// 循環(huán)建立初始堆

for (int i = length / 2; i >= 0; i--){

HeapAdjust(list, i, length);

}

n 個(gè)結(jié)點(diǎn),從第 0 層至第logn層。對(duì)于第 i 層的2i個(gè)點(diǎn)如果需要往下走logn?i步,那么把走的所有步相加得:

接下來(lái)就是排序的時(shí)間,即下面的代碼:

// 進(jìn)行n-1次循環(huán),完成排序

for (int i = length - 1; i > 0; i--){

// 最后一個(gè)元素和第一元素進(jìn)行交換

int temp = list[i];

list[i] = list[0];

list[0] = temp;

// 篩選 R[0] 結(jié)點(diǎn),得到i-1個(gè)結(jié)點(diǎn)的堆

HeapAdjust(list, 0, i);

}

HeapAdjust() 耗時(shí)logn,共 n 次,故排序時(shí)間為O(nlogn)。

堆的存儲(chǔ)表示是順序的。因?yàn)槎阉鶎?duì)應(yīng)的二叉樹(shù)為完全二叉樹(shù),而完全二叉樹(shù)通常采用順序存儲(chǔ)方式。

當(dāng)想得到一個(gè)序列中第k個(gè)最小的元素之前的部分排序序列,最好采用堆排序。

3.3 算法穩(wěn)定性

堆排序是一種不穩(wěn)定的排序方法。

因?yàn)樵诙训恼{(diào)整過(guò)程中,關(guān)鍵字進(jìn)行比較和交換所走的是該結(jié)點(diǎn)到葉子結(jié)點(diǎn)的一條路徑,因此對(duì)于相同的關(guān)鍵字就可能出現(xiàn)排在后面的關(guān)鍵字被交換到前面來(lái)的情況。

7. 歸并排序 MergeSort

歸并排序是建立在歸并操作上的一種有效的排序算法,該算法是采用分治法(Divide and Conquer)的一個(gè)非常典型的應(yīng)用。

1. 算法思想

該算法采用經(jīng)典的分治(divide-and-conquer)策略(分治法將問(wèn)題分(divide)成一些小的問(wèn)題然后遞歸求解,而治(conquer)的階段則將分的階段得到的各答案"修補(bǔ)"在一起,即分而治之)。

動(dòng)態(tài)效果示意圖:

分而治之:

1. 分階段

可以看到這種結(jié)構(gòu)很像一棵完全二叉樹(shù),本文的歸并排序我們采用遞歸去實(shí)現(xiàn)(也可采用迭代的方式去實(shí)現(xiàn))。分階段可以理解為就是遞歸拆分子序列的過(guò)程,遞歸深度為logn。

2. 治階段

再來(lái)看看治階段,我們需要將兩個(gè)已經(jīng)有序的子序列合并成一個(gè)有序序列,比如上圖中的最后一次合并,要將[4,5,7,8]和[1,2,3,6]兩個(gè)已經(jīng)有序的子序列,合并為最終序列[1,2,3,4,5,6,7,8],來(lái)看下實(shí)現(xiàn)步驟。

3. 算法分析

3.1. 歸并排序算法的性能

其中,log2n為以2為底,n的對(duì)數(shù)。

3.2 時(shí)間復(fù)雜度

歸并排序的形式就是一棵二叉樹(shù),它需要遍歷的次數(shù)就是二叉樹(shù)的深度,而根據(jù)完全二叉樹(shù)的可以得出它的時(shí)間復(fù)雜度是O(n*log2n)。

3.3 空間復(fù)雜度

由前面的算法說(shuō)明可知,算法處理過(guò)程中,需要一個(gè)大小為n的臨時(shí)存儲(chǔ)空間用以保存合并序列。

3.4 算法穩(wěn)定性

在歸并排序中,相等的元素的順序不會(huì)改變,所以它是穩(wěn)定的算法。

3.5 歸并排序和堆排序、快速排序的比較

若從空間復(fù)雜度來(lái)考慮:首選堆排序,其次是快速排序,最后是歸并排序。

若從穩(wěn)定性來(lái)考慮,應(yīng)選取歸并排序,因?yàn)槎雅判蚝涂焖倥判蚨际遣环€(wěn)定的。

若從平均情況下的排序速度考慮,應(yīng)該選擇快速排序。

8. 基數(shù)排序 RadixSort

基數(shù)排序是一種非比較型整數(shù)排序算法,其原理是將整數(shù)按位數(shù)切割成不同的數(shù)字,然后按每個(gè)位數(shù)分別比較。由于整數(shù)也可以表達(dá)字符串(比如名字或日期)和特定格式的浮點(diǎn)數(shù),所以基數(shù)排序也不是只能使用于整數(shù)。

1. 算法思想

基本思想:將所有待比較數(shù)值(正整數(shù))統(tǒng)一為同樣的數(shù)位長(zhǎng)度,數(shù)位較短的數(shù)前面補(bǔ)零。然后,從最低位開(kāi)始,依次進(jìn)行一次排序。這樣從最低位排序一直到最高位排序完成以后,數(shù)列就變成一個(gè)有序序列。

算法步驟:

將所有待比較數(shù)值(正整數(shù))統(tǒng)一為同樣的數(shù)位長(zhǎng)度,數(shù)位較短的數(shù)前面補(bǔ)零。

從最低位開(kāi)始,依次進(jìn)行一次排序。

這樣從最低位排序一直到最高位排序完成以后, 數(shù)列就變成一個(gè)有序序列。

基數(shù)排序的方式可以采用 LSD(Least significant digital)或 MSD(Most significant digital),LSD 的排序方式由鍵值的最右邊開(kāi)始,而 MSD 則相反,由鍵值的最左邊開(kāi)始。

不妨通過(guò)一個(gè)具體的實(shí)例來(lái)展示一下基數(shù)排序是如何進(jìn)行的。 設(shè)有一個(gè)初始序列為: R {50, 123, 543, 187, 49, 30, 0, 2, 11, 100}。

我們知道,任何一個(gè)阿拉伯?dāng)?shù),它的各個(gè)位數(shù)上的基數(shù)都是以 0~9 來(lái)表示的,所以我們不妨把 0~9 視為 10 個(gè)桶。

我們先根據(jù)序列的個(gè)位數(shù)的數(shù)字來(lái)進(jìn)行分類(lèi),將其分到指定的桶中。例如:R[0] = 50,個(gè)位數(shù)上是 0,將這個(gè)數(shù)存入編號(hào)為 0 的桶中。

分類(lèi)后,我們?cè)趶母鱾€(gè)桶中,將這些數(shù)按照從編號(hào) 0 到編號(hào) 9 的順序依次將所有數(shù)取出來(lái)。這時(shí),得到的序列就是個(gè)位數(shù)上呈遞增趨勢(shì)的序列。

按照個(gè)位數(shù)排序: {50, 30, 0, 100, 11, 2, 123, 543, 187, 49}。

接下來(lái),可以對(duì)十位數(shù)、百位數(shù)也按照這種方法進(jìn)行排序,最后就能得到排序完成的序列。

動(dòng)態(tài)效果示意圖:

3. 算法分析

3.1 基數(shù)排序的性能

其中,d代表數(shù)組元素最高為位數(shù),n代表元素個(gè)數(shù)。

3.2 時(shí)間復(fù)雜度

這個(gè)時(shí)間復(fù)雜度比較好計(jì)算:count * length;其中 count 為數(shù)組元素最高位數(shù),length為元素個(gè)數(shù);所以時(shí)間復(fù)雜度:O(n * d)

3.3 空間復(fù)雜度

空間復(fù)雜度是使用了兩個(gè)臨時(shí)的數(shù)組:10 + length;所以空間復(fù)雜度:O(n)。

3.4 算法穩(wěn)定性

在基數(shù)排序過(guò)程中,每次都是將當(dāng)前位數(shù)上相同數(shù)值的元素統(tǒng)一“裝桶”,并不需要交換位置。所以基數(shù)排序是穩(wěn)定的算法。

總結(jié)

以上是生活随笔為你收集整理的冒泡排序c++代码_八大排序算法(解释+代码+结果+算法优化)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。