數(shù)據(jù)結構第六章排序_第1頁
數(shù)據(jù)結構第六章排序_第2頁
數(shù)據(jù)結構第六章排序_第3頁
數(shù)據(jù)結構第六章排序_第4頁
數(shù)據(jù)結構第六章排序_第5頁
已閱讀5頁,還剩68頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

基本概念插入排序交換排序選擇排序歸并排序基數(shù)排序外部排序10-1排序的基本概念是記錄中的一個(或多個)字段,如果是

關鍵碼,則按關鍵碼排序;排序碼也

可以不是關鍵碼,則可能有多個記錄具

有相同的排序碼,排序的結果不惟一。將一個數(shù)據(jù)元素集合或序列重新

排列成一個按數(shù)據(jù)元素某個數(shù)據(jù)

項值有序的序列。排序排序碼穩(wěn)定排序不穩(wěn)定排序內(nèi)排序外排序假設{R0,R1,…,Rn-1}是由n個記錄組成

的文件,{K0,K1,…,Kn-1}是排序碼集合,

假設Ki=Kj(0<=i,j<=n-1,i≠j),且在排序

前的序列中Ri領先于Rj(即i<j),若在排

序后的序列中Ri仍領先于Rj,則稱所用

的排序方法是穩(wěn)定的,否則是不穩(wěn)定的。待排序的記錄在排序過程中全部存放在內(nèi)存

的稱為內(nèi)排序,如果排序過程中需要使用

外存的稱為外排序。排序方法可以分為五種:插入排序、選擇排序、

交換排序、基數(shù)排序和歸并排序。排序中的基本操作:比較關鍵碼大小和移動記錄。評價排序算法好壞的標準主要有兩條∶①執(zhí)行算法所需的時間;②執(zhí)行算法所需要的附加空間。排序的時間開銷可以用算法執(zhí)行中的比較和移動次數(shù)來表示。10-2插入排序插入排序的基本思想:每步將一個待排序的記錄按其

關鍵字大小插入到前面已排序表中的適當位置,直到

全部插入完為止。直接插入排序假設待排序的n個記錄{R0,R1,…,Rn-1}存放在數(shù)組中,

直接插入法是在插入記錄Ri(i=1,2…n-1)時,記錄集合

被劃分為兩個區(qū)間[R0,Ri-1]和[Ri,Rn-1],其中,

前一個子區(qū)間已經(jīng)排好序,后一個子區(qū)間是當前未

排序的部分,將排序碼Ki與Ki-1,Ki-2,…,K0依次比

較,找出應該插入的位置,將記錄Ri插入,原位置

的記錄向后順移。例:設待排序記錄的排序碼為:49,38,65,97,76,13,27,49,請用直接插入排法排序。i=2:[49]38659776132749i=3:[3849]659776132749i=4:[384965]9776132749i=5:[38496597]76132749i=6:[3849657697]132749i=7:[133849657697]27

49i=8:[13273849657697]49i=9:[1327384949657697]typedefstruct{KeyTypekey;

…;}DataType;voidInsertSort(DataTypeR[],intn){intI;for(i=2;i<=n;i++)

if(R[i].key<R[i-1].key){R[0]=R[i];for(j=i-1;R[0].dey<R[j].key;j--)R[j+1]=R[j];R[j+1]=R[0];}}算法分析如下:空間效率:只需要一個記錄的輔助空間。時間效率:最小比較記錄的次數(shù)為n-1=O(n);最大比較記錄的次數(shù)為(n+2)(n-1)/2=O(n2);最小移動記錄的次數(shù)為0次;最大移動記錄的次數(shù)為(n+4)(n-1)/2=O(n2)。

平均情況下,插入記錄大約同前面i/2個記錄進行關鍵碼比較和移動,因此插入排序的時間復雜度為O(n2)直接插入排序是穩(wěn)定的排序算法二分法插入排序由于插入排序的基本操作是在有序表中進行查找,而

查找的過程是可以用折半查找來實現(xiàn)的。由此實現(xiàn)

的排序稱為二分法插入排序。二分法插入排序必須采用順序存儲方式。voidB_InsertSort(DataTypeR[],intn){intI;intcow,high,mid;for(i=2;i<=n;i++){R[0]=R[i];low=1;high=i-1;while(low<=high){mid=(low+high)/2;if(R[0].key>R[mid].key)low=mid+1;elsehigh=mid-1;}for(j=i-1;j>=high+1;j--)R[j+1]=R[j];R[high+1]=R[0];}}i=2:[49]38659776132749i=3:[3849]659776132749i=4:[384965]9776132749i=5:[38496597]76132749i=6:[3849657697]132749i=7:[133849657697]2749i=8:[13273849657697]49i=9:[1327384949657697]low=1,high=1low=1,high=2low=1,high=3low=1,high=4low=1,high=5算法分析如下:定位一個關鍵碼的位置需比較次數(shù)至多為,比較次數(shù)時間復雜度為而移動記錄的次數(shù)和直接插入排序相同,

因此時間復雜度仍為O(n2)二分插入排序是一個穩(wěn)定的排序方法。表插入排序基本思想:在直接插入的基礎上減少移動次數(shù),主要

是在記錄中設置一個指針字段,記錄鏈接成鏈表,初

始時,鏈表為空,頭結點指針域置為0,并在頭結點數(shù)

據(jù)域放比所有記錄關鍵碼都大的整數(shù),然后,向鏈表

中插入結點typedefstruct{DataTypedata;intnext;}NodeType;NodeTypeR[n+1];MAX49386597761327490--------0112030445262738這個有序的鏈表,查找則只能順序查找,而不能隨機查找若需要,要發(fā)對記錄進行重排,使其在物理上有序。012345678voidB_InsertSort(NodeTypeR[],intn){inti,j,p;DataTypeS;j=R[0].next;i=1;while(i<n)if(i==j){j=R[j].next;i++;}elseif(i<j){p=R[j].next;S=R[i];R[i]=R[j];R[j]=S;R[i].next=j;j=p;}elsewhile(j<i)j=R[j].next;}012345678MAX4938659776132749681504723jip134986jip27381jij7p387655jij496970pjip497648jijp659770jijp769708ij希爾排序Shell排序又稱縮小增量排序,排序的基本思想是先取d1<n,

將整個待排記錄分成d1個組,所有距離為d1倍數(shù)的記錄放在同一組中,先在各組進行直接插入排序;然后,取d2<d1

重復上述分組和排序工作;直到di=1為止,就可以完成整個

的排序工作。Shell排序的一個特點是:子序列的構成不是簡單“逐段

分割”,而是將相隔某個增量的記錄組成一個子序列。di有各種取法,Shell取D.Knuth取49386597761327495504初始:

d1=10/2=549132738496555970476一趟排序后:

1327495504493865977604273855二趟排序后:13044938274955659776041338494938279776希爾排序是個不穩(wěn)定的排序方法voidShellInsert(DataTypeR[],intdk){inti;for(i=dk+1;i<=n;i++)if(R[i].key<R[i-dk].key){R[0]=R[i];for(j=i-dk;j>0&&R[0].key<R[j].key;j=j-dk)R[j+dk]=R[j];R[j+dk]=R[0];}}voidShellSort(DataTypeR[],intn,intd[],intt){intk;for(k=0;k<t;k++)ShellInsert(R,d[k]);}10-3交換排序交換排序的基本方法是兩兩比較待排序記錄的排序碼,

交換不滿足順序要求的偶對,直到全部滿足為止。冒泡排序的方法是先將序列中的第一個記錄R0與第二個

記錄R1比較,若前者大于后者,則兩個記錄交換位置,

否則不交換;然后,對新的第二個記錄R1與第三個記錄R2

做同樣的處理;依次類推,直到處理完第n-1個記錄和

第n個記錄,從(R0,R1)到(Rn-2,Rn-1)的n-1次比較和交換

過程稱為一次起泡。重復這樣起泡過程最多n-1次就能完

成排序.冒泡排序voidBubble_Sort(DataTypeR[],intn){inti,j,swap;

for(i=1;i<n;i++){swap=0;for(j=1;j<=n-i;j++)

if(R[j].key>R[j+1].key){R[0]=R[j];R[j]=R[j+1];R[j+1]=R[0];swap=1;}if(swap==0)break;}}13

0449

38

27

49

55

65

97

76041338492749769704

13

38

27

49

49

55

65

76

97

2738最好情況下:移動次數(shù)為0,

比較次數(shù)為n-1最差情況下:比較次數(shù)

穩(wěn)定的排序方法快速排序快速排序基本思想是:通過一趟排序?qū)⒋庞涗浄指?/p>

成獨立的兩部分,其中一部分記錄的關鍵字均比另一

部分記錄的關鍵字小,則可分別對這兩部分記錄繼續(xù)

進行排序,以達到整個序列有序。一趟快速排序的具體做法是:附設兩個指針i和j,它們的

初值分別是一個序列的第一個和最后一個記錄的位置,

設樞軸記錄的關鍵字為temp.key,在首先從j所指位置起

向前搜索直到第一個關鍵字小于temp.key的記錄和i記錄

交換,然后從i所指位置起向后搜索,找到第一個

關鍵字大于temp.key的記錄和j記錄互相交換,重復

交替這兩步直到i=j為止。491438749665849552749ij27iii74jjj8i96jj492714388496596495574ij278ii38j278142738496596495574ij65j55i96j49i658142738495549659674intPartition(DataTypeR[],inti,intj)

{R[0]=R[i];while(i<j){while(i<j&&R[j].key>=R[0].key)j--;if(i<j){R[i]=R[j];i++;}while(i<j&&R[i].key<R[0].key)i++;if(i<j){R[j]=R[i];j--;}}R[i]=R[0];returni;}voidQuick_Sort(DataTypeR[],ints,intt){if(s<t){i=Partition(R,s,t);Quick_Sort(R,s,i-1);Quick_Sort(R,i+1,t);}}voidQuick(DataTypeR[],intn){

Quick_Sort(R,1,n);}快速排序的記錄移動次數(shù)不大于比較次數(shù),所以,

快速排序的最壞時間復雜度應為O(n2),最好時間

復雜度為O(nlog2n)。4927651483855499674上例中對應的遞歸調(diào)用過程的二叉樹快速排序是通常被認為同數(shù)量級的排序方法中

平均性能最好的??焖倥判蚴且粋€不穩(wěn)定排序方法10-4選擇排序每一趟在n-i+1個記錄中選取關鍵碼最小的記錄作為

有序序列中第i個記錄,直到全部排完。簡單選擇排序基本方法是首先在所有記錄中選出排序碼最小的記錄,

與第一個記錄交換,然后在其余的記錄中再選出排序

碼最小的記錄與第二個記錄交換,以此類推,直到所

有記錄排好序。voidSelect_Sort(DataTypeR[],intn){inti,j,k;

for(i=1;i<n;i++){for(k=i,j=i+1;j<=n;j++)if(R[j].key<R[k].key)k=j;if(i!=k){R[0]=R[k];R[k]=R[i];R[i]=R[0];}}}4938659749132776i=1,k=6[13]38659749492776i=2,k=7[1327]659749493876i=3,k=7[132738]9749496576i=4,k=5[13273849]97496576i=5,k=6…直接選擇排序的比較次數(shù)與文件初始狀態(tài)無關。直接選擇排序的時間復雜度:最好移動次數(shù)為0,最壞移動次數(shù)為3(n-1)=O(n)。比較次數(shù)為n(n-1)/2=樹形選擇排序樹形選擇排序又稱錦標賽排序,是一種按照錦標賽的

思想進行選擇排序的方法。首先對n個記錄的關鍵字

進行兩兩比較,然后在n/2個較小者之間再進行兩兩

比較,如此重復,直至選出最小的記錄為止。493865977613274938651327381313M76M2727由于含有n個子結點的完全二叉樹的深度為log2n+1,

則在樹形選擇排序中,除了最小數(shù)值之外,每選擇

一個次小數(shù)僅需要進行l(wèi)og2n次比較,因此,它的時

間復雜度為O(nlogn)。但是,這種排序方法尚有輔

助存儲空間較多、和“最大值”進行多余比較等缺點。

為了彌補,威洛姆斯(J.willioms)在1964年提出了

另一種形式的選擇排序——堆排序。堆排序堆的概念:高有n個元素的序列{k1,k2,…,kn},當且僅當

滿足下述關系之一,稱這為堆。如果堆中根結點的排序碼最小,則稱為小根堆;如果堆中根結點的排序碼最大,則稱為大根堆。堆排序的思想是:首先設法把原始序列構造成一個堆,使得n個元素的最大值處于序列的第一個位置;然后交換序列第一元素(最大值元素)與最后一個元素。再把序列的前n-1個元素組成的子序列構成一個新堆,重復以上步驟,最終整個序列成為有序序列。堆排序的關鍵是:(1)如何將一個無序序列建成一個堆;

(2)如何把“去掉”了最大值元素后的序列

調(diào)整剩余元素為一個新的堆。構造初始堆是指把整個記錄從R1到Rn調(diào)整為一個大根堆。

完全二叉樹中,所有序號i>n/2的結點都是葉結點,以這

些結點為根的子樹均已是堆,只需依次將以序號

n/2,n/2-1,…,1結點為根的子樹調(diào)整為堆即可。

用篩選法為以Ri為根的完全二叉樹建堆,若Ri的左右子樹

都是堆,可以把Ri與其左右子樹根結點R2i+1,R2i+2中最大者

交換位置。若交換位置后破壞了子樹的堆特性,則再對這

棵子樹重復交換過程,直到以Ri為根結點的子樹成為堆。VoidheapAdjust(DataTypeR[],ints,intt){inti,j;DataTyperc;rc=R[s];i=s;for(j=2*i;j<=t;j=2*j){if(j<t&&R[j].key<R[j+1].key)j=j+1;if(rc.key>R[j].key)break;R[i]=R[j];i=j;}R[i]=rc;}05615948191126150105rcij61ij48ij1505voidHeapSort(DataTypeR[],intn){intI;for(i=n/2;i>0;i--)HeapAdjust(R,i,n);for(i=n;i>1;i--){R[0]=R[1];R[1]=R[i];R[i]=R[0];HeapAdjust(R,1,i-1);}}初始序列為26,5,77,1,61,11,59,15,48,19,請用堆排序法排序。(1)初始完全二叉樹(2)調(diào)整序號為5的結點(3)調(diào)整序號為4的結點(4)調(diào)整序號為3的結點(5)調(diào)整序號為2的結點(6)調(diào)整序號為1的結點(7)結點77與結點5互換(8)重建堆(9)結點61與結點1互換(10)重建堆(11)結點59與結點05互換(12)重建堆(13)結點48與結點1互換(14)重建堆(15)結點26與結點1互換(16)重建堆(17)結點19與結點5互換(18)重建堆(19)結點15與結點1互換(20)重建堆堆排序的時間耗費主要在構造初始堆,以及排序中去掉

最大元素后重建堆兩部分。初始建堆共調(diào)用HeapAdjust函數(shù)n/2次,每次將一個Ri(i<n/2)

為根的子樹樹調(diào)整為堆。個結點的完全二叉樹,其深度的結點層數(shù)依次為:0,1,1,2,2,2,…,h-1。

個,以它為根的子樹深度為h-m。第m層上結點數(shù)最多為HeapAdjust算法的每層上與兩個子女和排序碼值進行比較,

所以在m層上結點執(zhí)行初始建堆最多比較2(h-m)次,第m層

所有子樹建堆最多比較次數(shù)為第一部分初始建堆總的比較次數(shù)為排序中每去掉最大元素后需要重建堆。重建堆需要與

排序碼的比較次數(shù)為第二部分排序中重建堆比較花費總次數(shù)為整個堆排序總的比較次數(shù)為結點移動的次數(shù)小于比較次數(shù),故總的時間復雜度。堆排序是不穩(wěn)定的!歸并排序的基本思想是把待排序的文件分成若干個子文件,

先將每個子文件內(nèi)的記錄排序,再將已排序的子文件合并,

得到完全排序的文件。10-5歸并排序假設初始的序列含有n個記錄,可以看成n個有序的子序列,

每個子序列的長度為1,然后兩兩歸并,得到個長度為

2或1的有序子序列;再兩兩歸并,如此重復直到得到一個

長度為n的有序序列為止。這種排序方法稱為二路歸并排序。voidMerge(DataTypeR[],DataTypeR1[],ints,intm,intt)

{inti,j,k;i=s;j=m+1;k=s;while(i<=m&&j<=t)

if(R[i].key<R[j].key){R1[k]=R[i];k++;i++;}else{R1[k]=R[j];k++;j++;

}while(i<=m)

{R1[k]=R[i];k++;i++;}

while(j<=t){R1[k]=R[j];k++;j++;

}}voidMergePass(DataTypeR[],DataTypeR1[],intlen,intn)

{inti;for(i=1;i+2*len-1<n;i=i+2*len)Merge(R,R1,i,i+len-1,i+2*len-1)if(i+len-1<n)Merge(R,R1,i,i+len-1,n);elseif(i<=n)while(i<=n)R1[i++]=R[i+1];}歸并排序的迭代算法VoidMergeSort(DataTypeR[],intn){DataTypeR1[MAXNUM];intlen;len=1;while(len<n){MergePass(R,R1,len,n)len=2*len;MergePass(R1,R,len,n);}}歸并排序的遞歸算法voidMSort(DataTypeR[],DataTypeR1[],ints,intt){intm;if(s==t)R1[s]=R[s];else{m=(s+t)/2;MSort(R,R1,s,m);MSort(R,R1,m+1,t);Merge(R1,R,s,m,t);}}voidMergeSort(DataTypeR[],intn){DataTypeR1[MAXNUM];MSort(R,R1,1,n);}25

57

48

37

12

82

75

29

16

255737481282297516253748571229758216122529374857758216121625293748577582算法分析:時間復雜度:空間復雜度:和待排記錄等量的空間。

二路歸并算法是穩(wěn)定的。一般情況下很少用于內(nèi)部排序。10-6基數(shù)排序基數(shù)排序?qū)儆诜峙渑判颍峙渑判虻乃枷胧前雅判虼a

分解成若干部分,然后通過對各個部分排序碼的分別

排序,最終達到整個排序碼的排序?;鶖?shù)排序是采用“分配”與“收集”的辦法,用對多關鍵碼

進行排序的思想實現(xiàn)對單關鍵碼進行排序的方法。多關鍵碼排序1.以撲克牌排序為例。每張撲克牌有兩個“關鍵碼”:

花色和面值。其有序關系為:花色:梅花<方塊<紅心<黑桃面值:2<3<4<5<6<7<8<9<10<J<Q<K<A

可以先按花色排序,之后再按面值排序;

也可以先按面值排序,再按花色排序。文件中任一記錄R[i]的關鍵字均由d個分量

構成。

若這d個分量中每個分量都是一個獨立的關鍵字,則文件是多

關鍵字的(如撲克牌有兩個關鍵字:點數(shù)和花色);設單關鍵字的每個分量的取值范圍均是:

C0≤kj≤Crd-1(0≤j<d)

可能的取值個數(shù)rd稱為基數(shù)。

基數(shù)排序的基本思想是:從低位到高位依次對

Kj(j=d-1,d-2,…,0)進行箱排序。在d趟箱排

序中,所需的箱子數(shù)就是基數(shù)rd,這就是“基數(shù)

排序"名稱的由來。

2781090639305891845052690080830123456789q.e0123456789q.fq[0].e2781090639305891845050830082699300630831845052780081095892690123456789q.e0123456789q.f9300630831845052780081095892695050081099300632692780831845890123456789q.e0123456789q.f505008109930063269278083184589008063083109184269278505589930#defineKEY_NUM…#defineRADIX…#defineMAX_SPACE…Typedefstruct{KeyTypekeys[KEY_NUM];InfoTypeotheritems;intnext;}NodeType;Typedefstruct{intf;inte;}Q_Node;TypedefQ_NodeQueue[RADIX];voidDistribute(NodeTypeR[],inti,Queueq){intj;for(j=0;j<RADIX;j++)

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論