當(dāng)前位置:
首頁 >
排序算法:希尔、归并、快速、堆排序
發(fā)布時(shí)間:2025/3/21
26
豆豆
生活随笔
收集整理的這篇文章主要介紹了
排序算法:希尔、归并、快速、堆排序
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
排序算法
排序是非常常用,非常基本的算法。排序的方法有很多,比如插入排序、選擇排序、希爾排序、歸并排序、快速排序、堆排序。 本次試驗(yàn)重點(diǎn)實(shí)現(xiàn):希爾排序、歸并排序、快速排序、堆排序
插入排序
簡單說就是每次選未排序的隊(duì)列中最小的條目插入到已排序隊(duì)列的最后:選擇排序
選擇排序和插入有點(diǎn)像,是每次從拿未排序中的第一個(gè)條目插入到已排序中應(yīng)該插入的位置:希爾排序
希爾排序是插入排序的一種,是針對直接插入排序算法的改進(jìn)。希爾排序的基本思想是:先取一個(gè)小于count的增量increment,把表中Record分為increment組,所有距離為increment的Record為同一組,現(xiàn)在各組中進(jìn)行直接插入排序(insert_sort),然后減小increment重復(fù)分組和排序,知道increment=1,即所有Record放在同一組中進(jìn)行直接插入排序?yàn)橹埂?br />
【相關(guān)實(shí)驗(yàn)】
首先從類表List中派生子表Sortable_list。為了方便定義,我們可以重載這樣的構(gòu)造函數(shù)[cpp]?view plaincopy
2.實(shí)現(xiàn)表的排序一個(gè)重要的步驟是將Record換到相應(yīng)位置,即交換,所以編寫函數(shù)swap;
3.為了輸出每趟排序結(jié)果,我們再編寫一個(gè)全局函數(shù)print_out,由List的成員函數(shù)traverse()調(diào)用;調(diào)用的過程在置于swap之中,即每次有交換(或看做移動(dòng))則看做一趟排序。
相應(yīng)算法函數(shù)如下: [cpp]?view plaincopy
【實(shí)驗(yàn)結(jié)果】
歸并排序
歸并排序是采用分治的思想將兩個(gè)已排序的表合并成一個(gè)表歸并排序算法的基本思想是:先將一個(gè)表分成兩個(gè)表(當(dāng)個(gè)數(shù)是奇數(shù)時(shí),使左表的元素比右表多一)。對兩個(gè)表分別進(jìn)行歸并排序,然后將兩個(gè)已排序好的表合并。合并的思路就像將兩羅紙牌混成一摞,每次取頂上最小的紙牌。
【相關(guān)實(shí)驗(yàn)】
1.仍舊使用上述的Sortable_list
2.根據(jù)歸并排序的思想,每次子表仍舊使用歸并排序,可以通過遞歸實(shí)現(xiàn)。所以編寫遞歸函數(shù)recursive_merge_sort(),要把已排序好的子表合并,所以編寫合并子表的輔助函數(shù)merge()
3.為了輸出每趟排序結(jié)果,在歸并時(shí)merge中加入traverse(print_out) ?//但因?yàn)檫f歸調(diào)用的問題,很多次我們還是看不到過程
[cpp]?view plaincopy
【實(shí)驗(yàn)結(jié)果】
快速排序
快速排序是對冒泡排序的一種改進(jìn)。快速排序算法的基本思想是:每一趟排序中找一個(gè)點(diǎn)pivot,將表分割成獨(dú)立的兩部分,其中一部分的所有Record都比pivot小,另一部分比pivot大,然后再按此方法對這兩部分?jǐn)?shù)據(jù)分別進(jìn)行快速排序。?
【相關(guān)實(shí)驗(yàn)】
1.仍舊使用上述的Sortable_list。2.根據(jù)快速排序的思想,每趟排序?qū)⒈矸殖蓛刹糠秩缓笕耘f進(jìn)行快速排序,所以可以通過遞歸實(shí)現(xiàn),而為了調(diào)用遞歸函數(shù),我們首先編寫給定要排序范圍的參數(shù)的函數(shù)recursive_quick_sort(int low,int high)//之所以不將開始的quick_sort直接寫作遞歸函數(shù),是為了避免輸入?yún)?shù)而方便用戶調(diào)用。另外需要一個(gè)partition函數(shù),返回每趟排序之后的分點(diǎn)。
3.為了輸出每趟排序,我的想法是在每次遞歸中使用traverse(print_out)輸出,但卻不是想象的結(jié)果。因?yàn)檫f歸是每次遞歸出來之后才執(zhí)行函數(shù)print_out,除了前幾次可以看到結(jié)構(gòu),后來都是在排序好之后…所以我們?nèi)耘f通過swap函數(shù)實(shí)現(xiàn)輸出。
[cpp]?view plaincopy
【實(shí)驗(yàn)結(jié)果】
堆排序
堆排序是先將表中Record按大堆(或小堆)存放,使選取最大的Record變的極為容易,每次選取之后再提升堆。實(shí)現(xiàn)排序。繼續(xù):
【相關(guān)實(shí)驗(yàn)】
1.仍舊使用上述的Sortable_list。2.編寫heap_sort()函數(shù)。按思路,首先應(yīng)該建堆,然后取堆頂元素,之后對剩下元素重新建堆(提升堆),所以我們需要編寫build_heap()函數(shù),其通過inster_heap函數(shù)將元素一個(gè)個(gè)插入堆中。
最后實(shí)現(xiàn)heap_sort函數(shù)。
3.我們在每次插入堆時(shí)調(diào)用traverse(print_sort)實(shí)現(xiàn)對每趟排序的輸出。
[cpp]?view plaincopy
【實(shí)驗(yàn)結(jié)果】
結(jié)果分析
【希爾排序】
1.希爾排序是直接插入的一種改進(jìn),在效率上較直接插入排序有較大的改進(jìn)。直接插入排序每次只能將Record移動(dòng)一個(gè)位置,即增量increment為1,而希爾排序開始時(shí)增量較大,分組較多,每組Record數(shù)目少,故各組內(nèi)直接插入較快;increment遞減之后分組逐漸減少,Record增多,但由于已經(jīng)在increment較大時(shí)進(jìn)行過排序,表更接近于有序狀態(tài),新一趟的排序也較快。
2.我在實(shí)驗(yàn)中子表的排序是通過定義一個(gè)新表,然后調(diào)用直接插入函數(shù)。但這種方法效率并不高,而且浪費(fèi)空間;直接對子表進(jìn)行直接插入的排序是一種更好的方法。
3.希爾排序復(fù)雜度為:O(nlog2n) ? d =1希爾與直接插入排序基本一致
4.希爾排序是不穩(wěn)定的排序算法,即相等元素的順序可能改變
【歸并排序】
1.歸并排序在實(shí)現(xiàn)上用鏈?zhǔn)奖砀鼮楹侠?#xff0c;因?yàn)楹喜⒅行枰x新的表,即使我們通過動(dòng)態(tài)定義再刪除,以節(jié)省不必要的空間,這些工作仍是有些費(fèi)時(shí)。而鏈?zhǔn)奖碇皇欠祷刂羔?#xff0c;對節(jié)點(diǎn)Node的Node<Node_entry>*next部分進(jìn)行操作,不需要數(shù)據(jù)的移動(dòng)。但同時(shí)鏈?zhǔn)奖淼氖褂靡残枰獙χ羔樣惺煜さ恼莆?#xff0c;很容易出錯(cuò),先畫圖再編碼往往會(huì)有更清晰的思路。2.歸并排序的復(fù)雜度為:O(nlog2n)
3.歸并排序是穩(wěn)定的排序算法,即相等元素的順序不會(huì)改變
【快速排序】
1.復(fù)雜度:最好 O(nlog2n),最壞 O(n2)2.快速排序的最壞情況基于每次劃分對主元的選擇。基本的快速排序選取第一個(gè)元素作為主元。這樣在數(shù)組已經(jīng)有序的情況下,每次劃分將得到最壞的結(jié)果。一種比較常見的優(yōu)化方法是隨機(jī)化算法,即隨機(jī)選取一個(gè)元素作為主元。這種情況下雖然最壞情況仍然是O(n^2),但最壞情況不再依賴于輸入數(shù)據(jù),而是由于隨機(jī)函數(shù)取值不佳。
3.快速排序是一種不穩(wěn)定的排序算法
【堆排序】
1.實(shí)現(xiàn)堆排序很重要的一個(gè)操作就是建堆要將初始表調(diào)整為一個(gè)大根堆,就必須將它所對應(yīng)的完全二叉樹中以每一結(jié)點(diǎn)為根的子樹都調(diào)整為堆。顯然只有一個(gè)結(jié)點(diǎn)的樹是堆,而在完全二叉樹中,所有序號大于n/2的結(jié)點(diǎn)都是葉子,因此以這些結(jié)點(diǎn)為根的子樹均已是堆。這樣,我們只需依次將以序號為n/2,…,1的結(jié)點(diǎn)作為根的子樹都調(diào)整為堆即可。
2.堆[排序的時(shí)間,主要由建立初始堆和反復(fù)重建堆這兩部分的時(shí)間開銷構(gòu)成,堆排序的最壞時(shí)間復(fù)雜度為O(nlog2n)。
3.堆排序是不穩(wěn)定的排序算法
4.由于建初始堆所需的比較次數(shù)較多,所以堆排序不適宜于記錄數(shù)較少的文件。
堆排序每次在大堆中直接選擇出頂即最大的元素,這與選擇排序極為相似,但他們是不同的,堆排序的性能更為優(yōu)越。因?yàn)檫x擇排序中,為了從表中選出最小的記錄,必須進(jìn)行n-1次比較,然后在剩余表中選出關(guān)鍵字最小的記錄,又需要做n-2次比較。事實(shí)上,后面的n-2次比較中,有許多比較可能在前面的n-1次比較中已經(jīng)做過,但由于前一趟排序時(shí)未保留這些比較結(jié)果,所以后一趟排序時(shí)又重復(fù)執(zhí)行了這些比較操作。堆排序可通過樹形結(jié)構(gòu)保存部分比較結(jié)果,可減少比較次數(shù)。
(轉(zhuǎn)載請注明作者和出處:http://blog.csdn.net/xiaowei_cqu?未經(jīng)允許請勿用于商業(yè)用途)
總結(jié)
以上是生活随笔為你收集整理的排序算法:希尔、归并、快速、堆排序的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在没有安装OpenCV的电脑运行Open
- 下一篇: 正则表达式Regular Express