數(shù)據(jù)結(jié)構(gòu)嚴(yán)蔚敏 內(nèi)部排序_第1頁
數(shù)據(jù)結(jié)構(gòu)嚴(yán)蔚敏 內(nèi)部排序_第2頁
數(shù)據(jù)結(jié)構(gòu)嚴(yán)蔚敏 內(nèi)部排序_第3頁
數(shù)據(jù)結(jié)構(gòu)嚴(yán)蔚敏 內(nèi)部排序_第4頁
數(shù)據(jù)結(jié)構(gòu)嚴(yán)蔚敏 內(nèi)部排序_第5頁
已閱讀5頁,還剩95頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

10.1概述10.2插入排序10.3快速排序10.4選擇排序10.5歸并排序10.6基數(shù)排序10.7各種排序方法的綜合比較10內(nèi)部排序110.1概述一、排序的定義二、內(nèi)部排序和外部排序三、內(nèi)部排序方法的分類2一、什么是排序?排序是計(jì)算機(jī)內(nèi)經(jīng)常進(jìn)行的一種操作,其目的是將一組“無序”的記錄序列調(diào)整為“有序”的記錄序列。例如:將下列關(guān)鍵字序列52,49,80,36,14,58,61,23,97,75調(diào)整為14,23,36,49,52,58,61,75,80,973一般情況下,假設(shè)含n個記錄的序列為{R1,R2,…,Rn}其相應(yīng)的關(guān)鍵字序列為{K1,K2,…,Kn}這些關(guān)鍵字相互之間可以進(jìn)行比較,即在它們之間存在著這樣一個關(guān)系:

Kp1≤Kp2≤…≤Kpn按此固有關(guān)系將上式記錄序列重新排列為

{Rp1,Rp2,…,Rpn}的操作稱作排序。4二、內(nèi)部排序和外部排序若整個排序過程不需要訪問外存便能完成,則稱此類排序問題為內(nèi)部排序;

反之,若參加排序的記錄數(shù)量很大,整個序列的排序過程不可能在內(nèi)存中完成,則稱此類排序問題為外部排序。5三、內(nèi)部排序的方法

內(nèi)部排序的過程是一個逐步擴(kuò)大記錄的有序序列長度的過程。經(jīng)過一趟排序有序序列區(qū)無序序列區(qū)有序序列區(qū)無序序列區(qū)6

基于不同的“擴(kuò)大”

有序序列長度的方法,內(nèi)部排序方法大致可分下列幾種類型:插入類交換類選擇類歸并類其它方法7待排記錄的數(shù)據(jù)類型定義如下:#defineMAXSIZE1000

//待排順序表最大長度typedefintKeyType;

//關(guān)鍵字類型為整數(shù)類型typedefstruct{KeyTypekey;//關(guān)鍵字項(xiàng)InfoTypeotherinfo;//其它數(shù)據(jù)項(xiàng)}RcdType;//記錄類型typedefstruct{RcdTyper[MAXSIZE+1];//r[0]閑置intlength;//順序表長度}SqList;//順序表類型81.插入類

將無序子序列中的一個或幾個記錄“插入”到有序序列中,從而增加記錄的有序子序列的長度。92.交換類

通過“交換”無序序列中的記錄從而得到其中關(guān)鍵字最小或最大的記錄,并將它加入到有序子序列中,以此方法增加記錄的有序子序列的長度。103.選擇類

從記錄的無序子序列中“選擇”關(guān)鍵字最小或最大的記錄,并將它加入到有序子序列中,以此方法增加記錄的有序子序列的長度。114.歸并類

通過“歸并”兩個或兩個以上的記錄有序子序列,逐步增加記錄有序序列的長度。5.其它方法12

10.2插入排序13有序序列R[1..i-1]R[i]無序序列R[i..n]一趟直接插入排序的基本思想:有序序列R[1..i]無序序列R[i+1..n]14實(shí)現(xiàn)“一趟插入排序”可分三步進(jìn)行:3.將R[i]插入(復(fù)制)到R[j+1]的位置上。2.將R[j+1..i-1]中的所有記錄均后移一個位置;1.在R[1..i-1]中查找R[i]的插入位置,R[1..j].keyR[i].key<R[j+1..i-1].key;15直接插入排序(基于順序查找)表插入排序(基于鏈表存儲)不同的具體實(shí)現(xiàn)方法導(dǎo)致不同的算法描述折半插入排序(基于折半查找)希爾排序(基于逐趟縮小增量)16一、直接插入排序

利用“順序查找”實(shí)現(xiàn)“在R[1..i-1]中查找R[i]的插入位置”算法的實(shí)現(xiàn)要點(diǎn):17從R[i-1]起向前進(jìn)行順序查找,監(jiān)視哨設(shè)置在R[0];R[0]=R[i];//設(shè)置“哨兵”循環(huán)結(jié)束表明R[i]的插入位置為j+1R[0]jR[i]for(j=i-1;R[0].key<R[j].key;--j);//從后往前找j=i-1插入位置18對于在查找過程中找到的那些關(guān)鍵字不小于R[i].key的記錄,并在查找的同時實(shí)現(xiàn)記錄向后移動;for(j=i-1;R[0].key<R[j].key;--j);

R[j+1]=R[j]R[0]jR[i]j=i-1上述循環(huán)結(jié)束后可以直接進(jìn)行“插入”插入位置19令i=2,3,…,n,實(shí)現(xiàn)整個序列的排序。for(i=2;i<=n;++i)

if(R[i].key<R[i-1].key)

{在

R[1..i-1]中查找R[i]的插入位置;插入R[i];

}20voidInsertionSort(SqList&L){//對順序表L作直接插入排序。

for(i=2;i<=L.length;++i)if(L.r[i].key<L.r[i-1].key){

}}//InsertSortL.r[0]=L.r[i];//復(fù)制為監(jiān)視哨for(j=i-1;L.r[0].key<L.r[j].key;--j)L.r[j+1]=L.r[j];//記錄后移L.r[j+1]=L.r[0];//插入到正確位置21內(nèi)部排序的時間分析:實(shí)現(xiàn)內(nèi)部排序的基本操作有兩個:(2)“移動”記錄。(1)“比較”序列中兩個關(guān)鍵字的大??;22對于直接插入排序:最好的情況(關(guān)鍵字在記錄序列中順序有序):“比較”的次數(shù):最壞的情況(關(guān)鍵字在記錄序列中逆序有序):“比較”的次數(shù):0“移動”的次數(shù):“移動”的次數(shù):23

因?yàn)镽[1..i-1]是一個按關(guān)鍵字有序的有序序列,則可以利用折半查找實(shí)現(xiàn)“在R[1..i-1]中查找R[i]的插入位置”,如此實(shí)現(xiàn)的插入排序?yàn)檎郯氩迦肱判?。二、折半插入排?4voidBiInsertionSort(SqList&L){}//BInsertSort在L.r[1..i-1]中折半查找插入位置;for(i=2;i<=L.length;++i){}//forL.r[0]=L.r[i];//將L.r[i]暫存到L.r[0]for(j=i-1;j>=high+1;--j)L.r[j+1]=L.r[j];//記錄后移L.r[high+1]=L.r[0];//插入25low=1;high=i-1;while

(low<=high)

{}m=(low+high)/2;//折半if

(L.r[0].key<L.r[m].key)

high=m-1;//插入點(diǎn)在低半?yún)^(qū)else

low=m+1;//插入點(diǎn)在高半?yún)^(qū)2614364952805861239775ilowhighmmlowlowmhigh14364952586180239775ilowhighmhighmhighmlow例如:再如:插入位置插入位置L.rL.r27三、表插入排序?yàn)榱藴p少在排序過程中進(jìn)行的“移動”記錄的操作,必須改變排序過程中采用的存儲結(jié)構(gòu)。利用靜態(tài)鏈表進(jìn)行排序,并在排序完成之后,一次性地調(diào)整各個記錄相互之間的位置,即將每個記錄都調(diào)整到它們所應(yīng)該在的位置上。28voidLInsertionSort(ElemSL[],intn){//對記錄序列SL[1..n]作表插入排序SL[0].key=MAXINT;SL[0].next=1;SL[1].next=0;

for(i=2;i<=n;++i)for(j=0,k=SL[0].next;SL[k].key<=

SL[i].key;j=k,k=SL[k].next)

{SL[j].next=i;SL[i].next=k;

}//結(jié)點(diǎn)i插入在結(jié)點(diǎn)j和結(jié)點(diǎn)k之間}//LinsertionSort29算法中使用了三個指針:其中:p指示第i個記錄的當(dāng)前位置

i指示第i個記錄應(yīng)在的位置

q指示第i+1個記錄的當(dāng)前位置如何在排序之后調(diào)整記錄序列?30voidArrange(ElemSL[],intn){p=SL[0].next;//p指示第一個記錄的當(dāng)前位置

for(i=1;i<n;++i){

while(p<i)p=SL[p].next;

q=SL[p].next;//q指示尚未調(diào)整的表尾

if(p!=i){

SL[p]←→SL[i];

//交換記錄,使第i個記錄到位

SL[i].next=p;//指向被移走的記錄}

p=q;//p指示尚未調(diào)整的表尾,//為找第i+1個記錄作準(zhǔn)備

}}//Arrange31

四、希爾排序(又稱縮小增量排序)

基本思想:對待排記錄序列先作“宏觀”調(diào)整,再作“微觀”調(diào)整。所謂“宏觀”調(diào)整,指的是,“跳躍式”的插入排序。具體做法為:32將記錄序列分成若干子序列,分別對每個子序列進(jìn)行插入排序。其中,d

稱為增量,它的值在排序過程中從大到小逐漸縮小,直至最后一趟排序減為1。例如:將n個記錄分成d個子序列:{R[1],R[1+d],R[1+2d],…,R[1+kd]}{R[2],R[2+d],R[2+2d],…,R[2+kd]}…{R[d],R[2d],R[3d],…,R[kd],R[(k+1)d]}33例如:162512304711233691831

第一趟希爾排序,設(shè)增量d=51123

12

9

181625

36

30

4731

第二趟希爾排序,設(shè)增量d=3918

121123

162531

304736第三趟希爾排序,設(shè)增量d=1

91112161823253031364734voidShellInsert(SqList&L,intdk){

for(i=dk+1;i<=n;++i)

if(L.r[i].key<L.r[i-dk].key){

L.r[0]=L.r[i];//暫存在R[0]

for(j=i-dk;j>0&&(L.r[0].key<L.r[j].key);

j-=dk)L.r[j+dk]=L.r[j];//記錄后移,查找插入位置L.r[j+dk]=L.r[0];//插入

}//if}//ShellInsert35voidShellSort(SqList&L,intdlta[],intt){//增量為dlta[]的希爾排序

for(k=0;k<t;++t)ShellInsert(L,dlta[k]);//一趟增量為dlta[k]的插入排序}//ShellSort3610.3快速排序一、起泡排序二、一趟快速排序三、快速排序四、快速排序的時間分析37一、起泡排序

假設(shè)在排序過程中,記錄序列R[1..n]的狀態(tài)為:第i趟起泡排序無序序列R[1..n-i+1]有序序列R[n-i+2..n]n-i+1無序序列R[1..n-i]有序序列R[n-i+1..n]比較相鄰記錄,將關(guān)鍵字最大的記錄交換到n-i+1的位置上38voidBubbleSort(ElemR[],intn){

while(i>1){

}

//while}//BubbleSorti=n;i=lastExchangeIndex;//本趟進(jìn)行過交換的//最后一個記錄的位置if(R[j+1].key<R[j].key)

{

Swap(R[j],R[j+1]);

lastExchangeIndex=j;//記下進(jìn)行交換的記錄位置

}

//iffor(j=1;j<i;j++)lastExchangeIndex=1;39注意:2.一般情況下,每經(jīng)過一趟“起泡”,“i減一”,但并不是每趟都如此。例如:2553157989i=7i=6for(j=1;j<i;j++)if(R[j+1].key<R[j].key)…13i=21.起泡排序的結(jié)束條件為,

最后一趟沒有進(jìn)行“交換記錄”。40時間分析:最好的情況(關(guān)鍵字在記錄序列中順序有序):只需進(jìn)行一趟起泡“比較”的次數(shù):最壞的情況(關(guān)鍵字在記錄序列中逆序有序):需進(jìn)行n-1趟起泡“比較”的次數(shù):0“移動”的次數(shù):“移動”的次數(shù):n-141二、一趟快速排序(一次劃分)

目標(biāo):找一個記錄,以它的關(guān)鍵字作為“樞軸”,凡其關(guān)鍵字小于樞軸的記錄均移動至該記錄之前,反之,凡關(guān)鍵字大于樞軸的記錄均移動至該記錄之后。致使一趟排序之后,記錄的無序序列R[s..t]將分割成兩部分:R[s..i-1]和R[i+1..t],且

R[j].key≤R[i].key≤R[j].key(s≤j≤i-1)

樞軸(i+1≤j≤t)。42stlowhigh設(shè)R[s]=52為樞軸

將R[high].key和樞軸的關(guān)鍵字進(jìn)行比較,要求R[high].key≥

樞軸的關(guān)鍵字

將R[low].key和樞軸的關(guān)鍵字進(jìn)行比較,要求R[low].key≤

樞軸的關(guān)鍵字high23low80high14low52例如R[0]52lowhighhighhighlow43可見,經(jīng)過“一次劃分”,將關(guān)鍵字序列

52,49,80,36,14,58,61,97,23,75調(diào)整為:23,49,14,36,(52)58,61,97,80,75在調(diào)整過程中,設(shè)立了兩個指針:low和high,它們的初值分別為:s和t,之后逐漸減小high,增加low,并保證

R[high].key≥52,和R[low].key≤52,否則進(jìn)行記錄的“交換”。44intPartition(RedType&R[],intlow,inthigh)

{pivotkey=R[low].key;

while(low<high){

while(low<high&&

R[high].key>=pivotkey)

--high;

R[low]←→R[high];

while(low<high&&

R[low].key<=pivotkey)

++low;

R[low]←→R[high];

}

returnlow;//返回樞軸所在位置}//Partition45intPartition(RedTypeR[],intlow,inthigh)

{}//Partition

R[0]=R[low];pivotkey=R[low].key;//樞軸while(low<high){}while(low<high&&

R[high].key>=pivotkey)--high;//從右向左搜索R[low]=R[high];while(low<high&&

R[low].key<=pivotkey)++low;//從左向右搜索R[high]=R[low];R[low]=R[0];

returnlow;46三、快速排序

首先對無序的記錄序列進(jìn)行“一次劃分”,之后分別對分割所得兩個子序列“遞歸”進(jìn)行快速排序。無序的記錄序列無序記錄子序列(1)無序子序列(2)樞軸一次劃分分別進(jìn)行快速排序47void

QSort(RedType&R[],ints,intt)

{

//對記錄序列R[s..t]進(jìn)行快速排序

if(s<t-1){

//長度大于1

}}//QSortpivotloc=Partition(R,s,t);

//對R[s..t]進(jìn)行一次劃分QSort(R,s,pivotloc-1);

//對低子序列遞歸排序,pivotloc是樞軸位置QSort(R,pivotloc+1,t);

//對高子序列遞歸排序48voidQuickSort(SqList&L){

//對順序表進(jìn)行快速排序

QSort(L.r,1,L.length);}//QuickSort

第一次調(diào)用函數(shù)Qsort時,待排序記錄序列的上、下界分別為1和L.length。49若待排記錄的初始狀態(tài)為按關(guān)鍵字有序時,快速排序?qū)⑼懟癁槠鹋菖判?,其時間復(fù)雜度為O(n2)。為避免出現(xiàn)這種情況,需在進(jìn)行一次劃分之前,進(jìn)行“予處理”,即:先對R(s).key,R(t).key和R[(s+t)/2].key,進(jìn)行相互比較,然后取關(guān)鍵字為

“三者之中”的記錄為樞軸記錄。5010.4堆排序簡單選擇排序堆排序51一、簡單選擇排序假設(shè)排序過程中,待排記錄序列的狀態(tài)為:有序序列R[1..i-1]無序序列R[i..n]第i趟簡單選擇排序從中選出關(guān)鍵字最小的記錄有序序列R[1..i]無序序列R[i+1..n]52簡單選擇排序的算法描述如下:voidSelectSort(ElemR[],intn){

//對記錄序列R[1..n]作簡單選擇排序。

for(i=1;i<n;++i){

//選擇第i小的記錄,并交換到位

}}//SelectSortj=SelectMinKey(R,i);

//在R[i..n]中選擇關(guān)鍵字最小的記錄if(i!=j)R[i]←→R[j];

//與第i個記錄交換53時間性能分析

對n個記錄進(jìn)行簡單選擇排序,所需進(jìn)行的關(guān)鍵字間的比較次數(shù)總計(jì)為:

移動記錄的次數(shù),最小值為0,

最大值為3(n-1)。54二、堆排序堆是滿足下列性質(zhì)的數(shù)列{r1,r2,…,rn}:或堆的定義:{12,36,27,65,40,34,98,81,73,55,49}例如:是小頂堆{12,36,27,65,40,14,98,81,73,55,49}不是堆(小頂堆)(大頂堆)55rir2i

r2i+1

若將該數(shù)列視作完全二叉樹,則r2i是ri的左孩子;r2i+1是ri的右孩子。1236276549817355403498例如:是堆14不56

堆排序即是利用堆的特性對記錄序列進(jìn)行排序的一種排序方法。例如:建大頂堆{98,81,49,73,36,27,40,55,64,12}{12,81,49,73,36,27,40,55,64,98}交換98和12重新調(diào)整為大頂堆{81,73,49,64,36,27,40,55,12,98}{40,55,49,73,12,27,98,81,64,36}經(jīng)過篩選57voidHeapSort(HeapType&H){

//對順序表H進(jìn)行堆排序}//HeapSortfor(i=H.length/2;i>0;--i)

HeapAdjust(H.r,i,H.length);

//建大頂堆for(i=H.length;i>1;--i){H.r[1]←→H.r[i];

//將堆頂記錄和當(dāng)前未經(jīng)排序子序列//H.r[1..i]中最后一個記錄相互交換

HeapAdjust(H.r,1,i-1);

//對H.r[1]進(jìn)行篩選}58如何“建堆”?兩個問題:如何“篩選”?定義堆類型為:typedefSqListHeapType;//堆采用順序表表示之59所謂“篩選”指的是,對一棵左/右子樹均為堆的完全二叉樹,“調(diào)整”根結(jié)點(diǎn)使整個二叉樹也成為一個堆。堆堆篩選6098814973556412362740例如:是大頂堆12但在98和12進(jìn)行互換之后,它就不是堆了,因此,需要對它進(jìn)行“篩選”。98128173641298比較比較61void

HeapAdjust(RcdType&R[],int

s,int

m){//已知R[s..m]中記錄的關(guān)鍵字除R[s]之外均//滿足堆的特征,本函數(shù)自上而下調(diào)整R[s]的//關(guān)鍵字,使R[s..m]也成為一個大頂堆}//HeapAdjustrc=R[s];//暫存R[s]for

(j=2*s;j<=m;j*=2)

{//j初值指向左孩子自上而下的篩選過程;}R[s]=rc;

//將調(diào)整前的堆頂記錄插入到s位置62if

(rc.key>=R[j].key)

break;//再作“根”和“子樹根”之間的比較,//若“>=”成立,則說明已找到rc的插//入位置s,不需要繼續(xù)往下調(diào)整R[s]=R[j];s=j;

//否則記錄上移,尚需繼續(xù)往下調(diào)整if

(j<m

&&R[j].key<R[j+1].key)++j;//左/右“子樹根”之間先進(jìn)行相互比較//令j指示關(guān)鍵字較大記錄的位置63建堆是一個從下往上進(jìn)行“篩選”的過程。40554973816436122798例如:排序之前的關(guān)鍵字序列為123681734998817355

現(xiàn)在,左/右子樹都已經(jīng)調(diào)整為堆,最后只要調(diào)整根結(jié)點(diǎn),使整個二叉樹是個“堆”即可。9849406436122764堆排序的時間復(fù)雜度分析:1.對深度為k的堆,“篩選”所需進(jìn)行的關(guān)鍵字比較的次數(shù)至多為2(k-1);3.調(diào)整“堆頂”n-1次,總共進(jìn)行的關(guān)鍵字比較的次數(shù)不超過

2(log2(n-1)+log2(n-2)+…+log22)<2n(log2n)

因此,堆排序的時間復(fù)雜度為O(nlogn)。2.對n個關(guān)鍵字,建成深度為h(=log2n+1)的堆,

所需進(jìn)行的關(guān)鍵字比較的次數(shù)至多4n;6510.5歸并排序

歸并排序的過程基于下列基本思想進(jìn)行:

將兩個或兩個以上的有序子序列“歸并”為一個有序序列。66在內(nèi)部排序中,通常采用的是2-路歸并排序。即:將兩個位置相鄰的記錄有序子序列歸并為一個記錄的有序序列。有序序列R[l..n]有序子序列R[l..m]有序子序列R[m+1..n]這個操作對順序表而言,是輕而易舉的。67voidMerge(RcdTypeSR[],RcdType&TR[],

inti,intm,intn){

//將有序的記錄序列SR[i..m]和SR[m+1..n]//歸并為有序的記錄序列TR[i..n]}//Mergefor(j=m+1,k=i;i<=m&&j<=n;++k)

{

//將SR中記錄由小到大地并入TR

if(SR[i].key<=SR[j].key)TR[k]=SR[i++];

elseTR[k]=SR[j++];

}

……

68if(i<=m)TR[k..n]=SR[i..m];//將剩余的SR[i..m]復(fù)制到TRif(j<=n)TR[k..n]=SR[j..n];//將剩余的SR[j..n]復(fù)制到TR69歸并排序的算法如果記錄無序序列R[s..t]的兩部分R[s..(s+t)/2]和R[(s+t)/2+1..t]分別按關(guān)鍵字有序,則利用上述歸并算法很容易將它們歸并成整個記錄序列是一個有序序列。由此,應(yīng)該先分別對這兩部分進(jìn)行2-路歸并排序。70例如:52,23,80,36,68,14(s=1,t=6)[52,23,80]

[36,68,14][52,23][80][52][23,52][

23,52,80][36,68][14][36][68][36,68][14,36,68][14,23,36,52,68,80][23]71void

Msort(RcdTypeSR[],RcdType&TR1[],ints,intt)

{

//將SR[s..t]歸并排序?yàn)門R1[s..t]

if(s==t)TR1[s]=SR[s];

else

{}}//Msort……72m=(s+t)/2;//將SR[s..t]平分為SR[s..m]和SR[m+1..t]Msort(SR,TR2,s,m);//遞歸地將SR[s..m]歸并為有序的TR2[s..m]Msort(SR,TR2,m+1,t);//遞歸地SR[m+1..t]歸并為有序的TR2[m+1..t]Merge(TR2,TR1,s,m,t);//將TR2[s..m]和TR2[m+1..t]歸并到TR1[s..t]73voidMergeSort(SqList&L){//對順序表L作2-路歸并排序MSort(L.r,L.r,1,L.length);}//MergeSort容易看出,對n

個記錄進(jìn)行歸并排序的時間復(fù)雜度為Ο(nlogn)。即:每一趟歸并的時間復(fù)雜度為O(n),總共需進(jìn)行l(wèi)og2n趟。7410.6基數(shù)排序75

基數(shù)排序是一種借助“多關(guān)鍵字排序”的思想來實(shí)現(xiàn)“單關(guān)鍵字排序”的內(nèi)部排序算法。多關(guān)鍵字的排序鏈?zhǔn)交鶖?shù)排序76一、多關(guān)鍵字的排序

n個記錄的序列{R1,R2,…,Rn}對關(guān)鍵字(Ki0,Ki1,…,Kid-1)有序是指:其中:K0被稱為“最主”位關(guān)鍵字Kd-1被稱為“最次”位關(guān)鍵字對于序列中任意兩個記錄Ri和Rj(1≤i<j≤n)都滿足下列(詞典)有序關(guān)系:(Ki0,Ki1,…,Kid-1)<(Kj0,Kj1,…,Kjd-1)77實(shí)現(xiàn)多關(guān)鍵字排序通常有兩種作法:最低位優(yōu)先LSD法最高位優(yōu)先MSD法78先對K0進(jìn)行排序,并按K0的不同值將記錄序列分成若干子序列之后,分別對K1進(jìn)行排序,...…,依次類推,直至最后對最次位關(guān)鍵字排序完成為止。79先對Kd-1進(jìn)行排序,然后對Kd-2進(jìn)行排序,依次類推,直至對最主位關(guān)鍵字K0排序完成為止。排序過程中不需要根據(jù)“前一個”關(guān)鍵字的排序結(jié)果,將記錄序列分割成若干個(“前一個”關(guān)鍵字不同的)子序列。80

例如:學(xué)生記錄含三個關(guān)鍵字:系別、班號和班內(nèi)的序列號,其中以系別為最主位關(guān)鍵字。

無序序列對K2排序?qū)1排序?qū)0排序3,2,301,2,153,1,202,3,182,1,201,2,152,3,183,1,202,1,203,2,303,1,202,1,201,2,153,2,302,3,18

1,2,152,1,202,3,183,1,203,2,30LSD的排序過程如下:81二、鏈?zhǔn)交鶖?shù)排序假如多關(guān)鍵字的記錄序列中,每個關(guān)鍵字的取值范圍相同,則按LSD法進(jìn)行排序時,可以采用“分配-收集”的方法,其好處是不需要進(jìn)行關(guān)鍵字間的比較。對于數(shù)字型或字符型的單關(guān)鍵字,可以看成是由多個數(shù)位或多個字符構(gòu)成的多關(guān)鍵字,此時可以采用這種“分配-收集”的辦法進(jìn)行排序,稱作基數(shù)排序法。82例如:對下列這組關(guān)鍵字{209,386,768,185,247,606,230,834,539}首先按其“個位數(shù)”取值分別為0,1,…,9“分配”成10組,之后按從0至9的順序?qū)⑺鼈儭笆占痹谝黄?;然后按其“十位?shù)”取值分別為0,1,…,9“分配”

成10組,之后再按從0至9的順序?qū)⑺鼈儭笆占痹谝黄?;最后按其“百位?shù)”重復(fù)一遍上述操作。83

在計(jì)算機(jī)上實(shí)現(xiàn)基數(shù)排序時,為減少所需輔助存儲空間,應(yīng)采用鏈表作存儲結(jié)構(gòu),即鏈?zhǔn)交鶖?shù)排序,具體作法為:

1.待排序記錄以指針相鏈,構(gòu)成一個鏈表;2.“分配”時,按當(dāng)前“關(guān)鍵字位”所取值,將記錄分配到不同的“鏈隊(duì)列”中,每個隊(duì)列中記錄的“關(guān)鍵字位”相同;3.“收集”時,按當(dāng)前關(guān)鍵字位取值從小到大將各隊(duì)列首尾相鏈成一個鏈表;4.對每個關(guān)鍵字位均重復(fù)2)和3)兩步。84例如:p→369→367→167→239→237→138→230→139進(jìn)行第一次分配進(jìn)行第一次收集f[0]r[0]f[7]r[7]f[8]r[8]f[9]r[9]p→230→230←→367←→167→237→367→167→237→138→368→239→139→369←→239→139→138←

85進(jìn)行第二次分配p→230→237→138→239→139p→230→367→167→237→138→368→239→139f[3]r[3]f[6]r[6]→230←→237→138→239→139→367←→167→368→367→167→368進(jìn)行第二次收集86

進(jìn)行第三次收集之后便得到記錄的有序序列f[1]r[1]p→230→237→138→239→139→367→167→368進(jìn)行第三次分配f[2]r[2]f[3]r[3]→138←→139→167→230←→237→239→367←→368p→138→139→167→230→237→239→367→36887提醒注意:1.“分配”和“收集”的實(shí)際操

溫馨提示

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

最新文檔

評論

0/150

提交評論