排序算法全分析
排序簡(jiǎn)介
排序是數(shù)據(jù)處理中經(jīng)常使用的一種重要運(yùn)算,在計(jì)算機(jī)及其應(yīng)用系統(tǒng)中,花費(fèi)在排序上的時(shí)間在系統(tǒng)運(yùn)行時(shí)間中占有很大比重;并且排序本身對(duì)推動(dòng)算法分析的發(fā)展也起很大作用。目前已有上百種排序方法,但尚未有一個(gè)最理想的盡如人意的方法,本章介紹常用的如下排序方法,并對(duì)它們進(jìn)行分析和比較。
1、插入排序(直接插入排序、折半插入排序、希爾排序);
2、交換排序(起泡排序、快速排序);
3、選擇排序(直接選擇排序、堆排序);
4、歸并排序;
5、基數(shù)排序;
學(xué)習(xí)重點(diǎn)
1、掌握排序的基本概念和各種排序方法的特點(diǎn),并能加以靈活應(yīng)用;
2、掌握插入排序(直接插入排序、折半插入排序、希爾排序)、交換排序(起泡排序、快速排序)、選擇排序(直接選擇排序、堆排序)、二路歸并排序的方法及其性能分析方法;
3、了解基數(shù)排序方法及其性能分析方法。
排序(sort)或分類
??? 所謂排序,就是要整理文件中的記錄,使之按關(guān)鍵字遞增(或遞減)次序排列起來(lái)。其確切定義如下:
輸入:n個(gè)記錄R1,R2,…,Rn,其相應(yīng)的關(guān)鍵字分別為K1,K2,…,Kn。
輸出:Ril,Ri2,…,Rin,使得Ki1≤Ki2≤…≤Kin。(或Ki1≥Ki2≥…≥Kin)。
1.被排序?qū)ο?-文件
被排序的對(duì)象--文件由一組記錄組成。
記錄則由若干個(gè)數(shù)據(jù)項(xiàng)(或域)組成。其中有一項(xiàng)可用來(lái)標(biāo)識(shí)一個(gè)記錄,稱為關(guān)鍵字項(xiàng)。該數(shù)據(jù)項(xiàng)的值稱為關(guān)鍵字(Key)。
? 注意:
??? 在不易產(chǎn)生混淆時(shí),將關(guān)鍵字項(xiàng)簡(jiǎn)稱為關(guān)鍵字。
2.排序運(yùn)算的依據(jù)--關(guān)鍵字
??? 用來(lái)作排序運(yùn)算依據(jù)的關(guān)鍵字,可以是數(shù)字類型,也可以是字符類型。
??? 關(guān)鍵字的選取應(yīng)根據(jù)問(wèn)題的要求而定。
【例】在高考成績(jī)統(tǒng)計(jì)中將每個(gè)考生作為一個(gè)記錄。每條記錄包含準(zhǔn)考證號(hào)、姓名、各科的分?jǐn)?shù)和總分?jǐn)?shù)等項(xiàng)內(nèi)容。若要惟一地標(biāo)識(shí)一個(gè)考生的記錄,則必須用"準(zhǔn)考證號(hào)"作為關(guān)鍵字。若要按照考生的總分?jǐn)?shù)排名次,則需用"總分?jǐn)?shù)"作為關(guān)鍵字。
排序的穩(wěn)定性
??? 當(dāng)待排序記錄的關(guān)鍵字均不相同時(shí),排序結(jié)果是惟一的,否則排序結(jié)果不唯一。
??? 在待排序的文件中,若存在多個(gè)關(guān)鍵字相同的記錄,經(jīng)過(guò)排序后這些具有相同關(guān)鍵字的記錄之間的相對(duì)次序保持不變,該排序方法是穩(wěn)定的;若具有相同關(guān)鍵字的記錄之間的相對(duì)次序發(fā)生變化,則稱這種排序方法是不穩(wěn)定的。
? 注意:
??? 排序算法的穩(wěn)定性是針對(duì)所有輸入實(shí)例而言的。即在所有可能的輸入實(shí)例中,只要有一個(gè)實(shí)例使得算法不滿足穩(wěn)定性要求,則該排序算法就是不穩(wěn)定的。
排序方法的分類
1.按是否涉及數(shù)據(jù)的內(nèi)、外存交換分
??? 在排序過(guò)程中,若整個(gè)文件都是放在內(nèi)存中處理,排序時(shí)不涉及數(shù)據(jù)的內(nèi)、外存交換,則稱之為內(nèi)部排序(簡(jiǎn)稱內(nèi)排序);反之,若排序過(guò)程中要進(jìn)行數(shù)據(jù)的內(nèi)、外存交換,則稱之為外部排序。
? 注意:
??? ① 內(nèi)排序適用于記錄個(gè)數(shù)不很多的小文件
??? ② 外排序則適用于記錄個(gè)數(shù)太多,不能一次將其全部記錄放人內(nèi)存的大文件。
2.按策略劃分內(nèi)部排序方法
??? 可以分為五類:插入排序、選擇排序、交換排序、歸并排序和分配排序。
排序算法分析
1.排序算法的基本操作
??? 大多數(shù)排序算法都有兩個(gè)基本的操作:
(1) 比較兩個(gè)關(guān)鍵字的大小;
(2) 改變指向記錄的指針或移動(dòng)記錄本身。
? 注意:
??? 第(2)種基本操作的實(shí)現(xiàn)依賴于待排序記錄的存儲(chǔ)方式。
2.待排文件的常用存儲(chǔ)方式
(1) 以順序表(或直接用向量)作為存儲(chǔ)結(jié)構(gòu)
??? 排序過(guò)程:對(duì)記錄本身進(jìn)行物理重排(即通過(guò)關(guān)鍵字之間的比較判定,將記錄移到合適的位置)
(2) 以鏈表作為存儲(chǔ)結(jié)構(gòu)
排序過(guò)程:無(wú)須移動(dòng)記錄,僅需修改指針。通常將這類排序稱為鏈表(或鏈?zhǔn)?排序;
(3) 用順序的方式存儲(chǔ)待排序的記錄,但同時(shí)建立一個(gè)輔助表(如包括關(guān)鍵字和指向記錄位置的指針組成的索引表)
排序過(guò)程:只需對(duì)輔助表的表目進(jìn)行物理重排(即只移動(dòng)輔助表的表目,而不移動(dòng)記錄本身)。適用于難于在鏈表上實(shí)現(xiàn),仍需避免排序過(guò)程中移動(dòng)記錄的排序方法。
3.排序算法性能評(píng)價(jià)
(1) 評(píng)價(jià)排序算法好壞的標(biāo)準(zhǔn)
評(píng)價(jià)排序算法好壞的標(biāo)準(zhǔn)主要有兩條:
??? ① 執(zhí)行時(shí)間和所需的輔助空間
??? ② 算法本身的復(fù)雜程度
(2) 排序算法的空間復(fù)雜度
若排序算法所需的輔助空間并不依賴于問(wèn)題的規(guī)模n,即輔助空間是O(1),則稱之為就地排序(In-PlaceSou)。
非就地排序一般要求的輔助空間為O(n)。
(3) 排序算法的時(shí)間開(kāi)銷
大多數(shù)排序算法的時(shí)間開(kāi)銷主要是關(guān)鍵字之間的比較和記錄的移動(dòng)。有的排序算法其執(zhí)行時(shí)間不僅依賴于問(wèn)題的規(guī)模,還取決于輸入實(shí)例中數(shù)據(jù)的狀態(tài)。
文件的順序存儲(chǔ)結(jié)構(gòu)表示
? #define n l00 //假設(shè)的文件長(zhǎng)度,即待排序的記錄數(shù)目
? typedef int KeyType; //假設(shè)的關(guān)鍵字類型
? typedef struct{ //記錄類型
??? KeyType key; //關(guān)鍵字項(xiàng)
??? InfoType otherinfo;//其它數(shù)據(jù)項(xiàng),類型InfoType依賴于具體應(yīng)用而定義
?? }RecType;
? typedef RecType SeqList[n+1];//SeqList為順序表類型,表中第0個(gè)單元一般用作哨兵
? 注意:
??? 若關(guān)鍵字類型沒(méi)有比較算符,則可事先定義宏或函數(shù)來(lái)表示比較運(yùn)算。
【例】關(guān)鍵字為字符串時(shí),可定義宏"#define LT(a,b)(Stromp((a),(b))<0)"。那么算法中"a<b"可用"LT(a,b)"取代。若使用C++,則定義重載的算符"<"更為方便。
?
按平均時(shí)間將排序分為四類:
(1)平方階(O(n2))排序
??? 一般稱為簡(jiǎn)單排序,例如直接插入、直接選擇和冒泡排序;
(2)線性對(duì)數(shù)階(O(nlgn))排序
??? 如快速、堆和歸并排序;
(3)O(n1+£)階排序
??? £是介于0和1之間的常數(shù),即0<£<1,如希爾排序;
(4)線性階(O(n))排序
??? 如桶、箱和基數(shù)排序。
各種排序方法比較
??? ?簡(jiǎn)單排序中直接插入最好,快速排序最快,當(dāng)文件為正序時(shí),直接插入和冒泡均最佳。
影響排序效果的因素
??? 因?yàn)椴煌呐判蚍椒ㄟm應(yīng)不同的應(yīng)用環(huán)境和要求,所以選擇合適的排序方法應(yīng)綜合考慮下列因素:
①待排序的記錄數(shù)目n;
②記錄的大小(規(guī)模);
③關(guān)鍵字的結(jié)構(gòu)及其初始狀態(tài);
④對(duì)穩(wěn)定性的要求;
⑤語(yǔ)言工具的條件;
⑥存儲(chǔ)結(jié)構(gòu);
⑦時(shí)間和輔助空間復(fù)雜度等。
不同條件下,排序方法的選擇
(1)若n較小(如n≤50),可采用直接插入或直接選擇排序。
??? 當(dāng)記錄規(guī)模較小時(shí),直接插入排序較好;否則因?yàn)橹苯舆x擇移動(dòng)的記錄數(shù)少于直接插人,應(yīng)選直接選擇排序?yàn)橐恕?br />(2)若文件初始狀態(tài)基本有序(指正序),則應(yīng)選用直接插人、冒泡或隨機(jī)的快速排序?yàn)橐?#xff1b;
(3)若n較大,則應(yīng)采用時(shí)間復(fù)雜度為O(nlgn)的排序方法:快速排序、堆排序或歸并排序。
??? 快速排序是目前基于比較的內(nèi)部排序中被認(rèn)為是最好的方法,當(dāng)待排序的關(guān)鍵字是隨機(jī)分布時(shí),快速排序的平均時(shí)間最短;
??? 堆排序所需的輔助空間少于快速排序,并且不會(huì)出現(xiàn)快速排序可能出現(xiàn)的最壞情況。這兩種排序都是不穩(wěn)定的。
??? 若要求排序穩(wěn)定,則可選用歸并排序。但本章介紹的從單個(gè)記錄起進(jìn)行兩兩歸并的? 排序算法并不值得提倡,通常可以將它和直接插入排序結(jié)合在一起使用。先利用直接插入排序求得較長(zhǎng)的有序子文件,然后再兩兩歸并之。因?yàn)橹苯硬迦肱判蚴欠€(wěn)定的,所以改進(jìn)后的歸并排序仍是穩(wěn)定的。
4)在基于比較的排序方法中,每次比較兩個(gè)關(guān)鍵字的大小之后,僅僅出現(xiàn)兩種可能的轉(zhuǎn)移,因此可以用一棵二叉樹(shù)來(lái)描述比較判定過(guò)程。
??? 當(dāng)文件的n個(gè)關(guān)鍵字隨機(jī)分布時(shí),任何借助于"比較"的排序算法,至少需要O(nlgn)的時(shí)間。
??? 箱排序和基數(shù)排序只需一步就會(huì)引起m種可能的轉(zhuǎn)移,即把一個(gè)記錄裝入m個(gè)箱子之一,因此在一般情況下,箱排序和基數(shù)排序可能在O(n)時(shí)間內(nèi)完成對(duì)n個(gè)記錄的排序。但是,箱排序和基數(shù)排序只適用于像字符串和整數(shù)這類有明顯結(jié)構(gòu)特征的關(guān)鍵字,而當(dāng)關(guān)鍵字的取值范圍屬于某個(gè)無(wú)窮集合(例如實(shí)數(shù)型關(guān)鍵字)時(shí),無(wú)法使用箱排序和基數(shù)排序,這時(shí)只有借助于"比較"的方法來(lái)排序。
??? 若n很大,記錄的關(guān)鍵字位數(shù)較少且可以分解時(shí),采用基數(shù)排序較好。雖然桶排序?qū)﹃P(guān)鍵字的結(jié)構(gòu)無(wú)要求,但它也只有在關(guān)鍵字是隨機(jī)分布時(shí)才能使平均時(shí)間達(dá)到線性階,否則為平方階。同時(shí)要注意,箱、桶、基數(shù)這三種分配排序均假定了關(guān)鍵字若為數(shù)字時(shí),則其值均是非負(fù)的,否則將其映射到箱(桶)號(hào)時(shí),又要增加相應(yīng)的時(shí)間。
(5)有的語(yǔ)言(如Fortran,Cobol或Basic等)沒(méi)有提供指針及遞歸,導(dǎo)致實(shí)現(xiàn)歸并、快速(它們用遞歸實(shí)現(xiàn)較簡(jiǎn)單)和基數(shù)(使用了指針)等排序算法變得復(fù)雜。此時(shí)可考慮用其它排序。
(6)本章給出的排序算法,輸人數(shù)據(jù)均是存儲(chǔ)在一個(gè)向量中。當(dāng)記錄的規(guī)模較大時(shí),為避免耗費(fèi)大量的時(shí)間去移動(dòng)記錄,可以用鏈表作為存儲(chǔ)結(jié)構(gòu)。譬如插入排序、歸并排序、基數(shù)排序都易于在鏈表上實(shí)現(xiàn),使之減少記錄的移動(dòng)次數(shù)。但有的排序方法,如快速排序和堆排序,在鏈表上卻難于實(shí)現(xiàn),在這種情況下,可以提取關(guān)鍵字建立索引表,然后對(duì)索引表進(jìn)行排序。然而更為簡(jiǎn)單的方法是:引人一個(gè)整型向量t作為輔助表,排序前令t[i]=i(0≤i<n),若排序算法中要求交換R[i]和R[j],則只需交換t[i]和t[j]即可;排序結(jié)束后,向量t就指示了記錄之間的順序關(guān)系:
??????? R[t[0]].key≤R[t[1]].key≤…≤R[t[n-1]].key
? 若要求最終結(jié)果是:
?????? R[0].key≤R[1].key≤…≤R[n-1].key
則可以在排序結(jié)束后,再按輔助表所規(guī)定的次序重排各記錄,完成這種重排的時(shí)間是O(n)。
轉(zhuǎn)載于:https://www.cnblogs.com/songQQ/archive/2009/09/28/1575830.html
總結(jié)
- 上一篇: ASP.NET2.0通用数据访问类
- 下一篇: 给Repeater、Datalist和D