數(shù)據(jù)結構(第2版)(C語言實現(xiàn))課件:排序_第1頁
數(shù)據(jù)結構(第2版)(C語言實現(xiàn))課件:排序_第2頁
數(shù)據(jù)結構(第2版)(C語言實現(xiàn))課件:排序_第3頁
數(shù)據(jù)結構(第2版)(C語言實現(xiàn))課件:排序_第4頁
數(shù)據(jù)結構(第2版)(C語言實現(xiàn))課件:排序_第5頁
已閱讀5頁,還剩52頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

排序

排序(sorting)是計算機程序設計的一個特別重要的技術,計算機的各個應用領域都有它的身影。如在處理學生考試成績和元素的查找等都涉及到了對數(shù)據(jù)的排序。排列有序的折半查找要比順序查找的效率要高許多。本章主要給大家介紹幾種常用的排序技術:插入排序、選擇排序、交換排序、歸并排序和基數(shù)排序。

本章重點和難點:

1、希爾排序

2、快速排序

3、堆排序

4、歸并排序

5、基數(shù)排序8.1基本概念

排序:把一個無序的元素序列按照元素的關鍵字遞增或遞減排列為有序的序列。假設包含n個元素(記錄)的序列

(E1,E2,…,En)

其對應的關鍵字為

(k1,k2,…,kn)

需確定1,2,…,n的一種排列p1,p2,…,pn,使關鍵字滿足以下非遞減(或非遞增)關系:

kp1≤kp2≤…≤kpn

從而使元素構成一個非遞減(或非遞增)的序列:

(Ep1,Ep2,…,Epn)

這樣的一種操作被稱為排序。8.1基本概念

穩(wěn)定排序和不穩(wěn)定排序:在待排序的記錄序列中,若存在兩個或兩個以上關鍵字想到呢個的記錄。假設ki=kj(1≤i≤n,1≤j≤n,i≠j),且排序前的對應的記錄Ei領先于Ej(即i<j)。若在排序之后,如果元素Ei仍領先于Ej,則稱這種排序采用的方法是穩(wěn)定的。如果經(jīng)過排序之后,元素Ej領先于Ei(即i<j),則稱這種排序方法是不穩(wěn)定的。一個排序算法的好壞可以主要通過時間復雜度、空間復雜度和穩(wěn)定性來衡量。無論算法穩(wěn)定還是不穩(wěn)定的,都不會影響到排序的最終結果。8.1基本概念

內排序和外排序:由于待排序的記錄數(shù)量不同,使得排序過程中涉及的存儲器不同,可將排序方法分為兩類:內部排序和外部排序。內部排序也稱為內排序,指的是待排序記錄存放在計算機隨機存儲器中進行的排序過程;外部排序也稱為外排序,指的是待排序記錄的數(shù)據(jù)流很大,以致內存一次不能容納全部記錄,在排序的過程中需要不斷對外存進行訪問的排序過程。8.1基本概念

內排序的方法有許多,按照排序過程中采用的策略將排序分為幾個大類:插入排序、選擇排序、交換排序和歸并排序。在排序過程中,需要以下兩種基本操作:(1)比較兩個元素相應關鍵字的大?。唬?)將元素從一個位置移動到另一個位置。其中,第(1)種操作對大多數(shù)排序方法來說都是必要的,第(2)種操作可通過改變記錄的存儲方式可以避免。8.1基本概念待排序的記錄序列有3種存儲方式:(1)順序存儲。待排序的元素存儲在一組連續(xù)的存儲單元中,這類似于線性表的順序存儲,在序列中相鄰的兩個記錄Ei和Ej,它們的物理位置也相鄰。在這種存儲方式中,記錄之間的次序關系由其存儲位置決定,則實現(xiàn)排序必須要移動記錄。(2)鏈式存儲。待排序元素存儲在一組不連續(xù)的存儲單元中,這類似于線性表的鏈式存儲,序列中相鄰的兩個記錄Ei和Ej,其物理位置不一定相鄰。在這種存儲方式中,記錄之間的關系由附設的指針指示,在進行排序時,不需要移動元素,只需要修改指針即可。(3)靜態(tài)鏈表。帶排序記錄存放在靜態(tài)鏈表中,記錄之間的關系由被稱為游標的指針指示,實現(xiàn)排序不需要移動元素,只需要修改游標即可。8.2插入排序8.2.1直接插入排序

直接插入排序(StraightInsertionSort)是一種最簡單的插入排序算法?;舅惴ㄋ枷耄杭僭O待排序元素有n個,初始時,已排序子集只有一個元素,即第1個元素;未排序子集是剩下的n-1個元素。

例如,有4個待排序元素22、6、17和8,排序前的狀態(tài)如圖9.1所示。8.2插入排序第1趟排序:將無序集中的第一個元素,也就是6與有序集中的元素22進行比較,因為22>6,所以需要先將22向后移動一個位置,然后將6插入到第一個位置,如圖8.2所示。其中,陰影部分表示無序集,白色部分表示有序集。第2趟排序:將無序集的元素17從右到左依次與有序集中的元素比較,即先與22比較,因為17<22,所以先將22向后移動一個位置,然后比較17與第1個元素6的大小,因為17>6,所以將17放在第2個元素的位置,如圖8.3所示。8.2插入排序第3趟排序:將待排序集合中的元素8與已經(jīng)有序的元素集合從右到左依次比較,先與22比較。因為8<22,所以需要將22向后移動一個位置并與前一個元素17比較。由于8<17,將17向后移動并繼續(xù)與6進行比較。因為8>6,所以將8放在第2個位置,如圖8.4所示。8.2插入排序

假設待排序元素有8個,分別是17、46、32、87、58、9、50、38。使用直接插入排序對該元素序列的排序過程如圖8.5所示。8.2插入排序直接插入排序算法描述如下。voidInsertSort(SqList*L)/*直接插入排序*/{ inti,j; DataTypet; for(i=1;i<L->length;i++)/*前i個元素已經(jīng)有序,從第i+1個元素開始與前i個有序的關鍵字比較*/ { t=L->data[i+1]; /*取出第i+1個元素,即待排序的元素*/ j=i; while(j>-1&&t.key<L->data[j].key)/*尋找當前元素的合適位置*/ { L->data[j+1]=L->data[j]; j--; } L->data[j+1]=t; /*將當前元素插入合適的位置*/ }}8.2插入排序8.2.2折半插入排序折半插入排序算法是直接插入排序的改進。它的主要改進在于,在已經(jīng)有序的集合中使用折半查找法確定待排序元素的插入位置。在找到要插入的位置后,將待排序元素插入到相應的位置。假設待排序元素有7個:67、53、73、21、34、98、12。使用折半插入排序對該元素序列第一趟排序過程如圖8.6所示。8.2插入排序第2趟折半插入排序過程如圖8.7所示。8.2插入排序voidBinInsertSort(SqList*L)/*折半插入排序*/{ inti,j,mid,low,high; DataTypet; for(i=1;i<L->length;i++) { t=L->data[i+1]; /*取出第i+1個元素,即待排序的元素*/ low=1,high=i; while(low<=high) /*利用折半查找思想尋找當前元素的合適位置*/ { mid=(low+high)/2; if(L->data[mid].key>t.key) high=mid-1; else low=mid+1; } for(j=i;j>=low;j--) /*移動元素,空出要插入的位置*/ L->data[j+1]=L->data[j]; L->data[low]=t; /*將當前元素插入合適的位置*

}}8.2插入排序8.2.3希爾排序希爾排序(shell’ssort)也稱為縮小增量排序(diminishingincrementsort),它也屬于插入排序類的算法,但時間效率比前幾種排序有較大改進。

例如,利用希爾排序的算法思想,對元素的關鍵字序列(56,22,67,32,59,12,89,26,48,37)進行排序,其排序過程如圖8.8所示。8.2插入排序voidShellInsert(SqList*L,intc)/*對順序表L進行一次希爾排序,c是增量*/{ inti,j; DataTypet; for(i=c+1;i<=L->length;i++)/*將距離為c的元素作為一個子序列進行排序*/ { if(L->data[i].key<L->data[i-c].key) /*如果后者小于前者,則需要移動元素*/ { t=L->data[i]; for(j=i-c;j>0&&t.key<L->data[j].key;j=j-c) L->data[j+c]=L->data[j]; L->data[j+c]=t;/*依次將元素插入到正確的位置*/ } }}8.2插入排序voidShellInsertSort(SqList*L,intdelta[],intm)/*希爾排序,每次調用算法ShellInsert,delta是存放增量的數(shù)組*/{ inti; for(i=0;i<m;i++) /*進行m次希爾插入排序*/ { ShellInsert(L,delta[i]); }}希爾排序的分析是一個非常復雜的事情,問題主要在于希爾排序選擇的增量,但是經(jīng)過大量的研究,當增量的序列為2m-k+1-1時,其中m為排序的次數(shù),1≤k≤t,其時間復雜度為O(n3/2)。希爾排序的空間復雜度為O(1)。

8.2插入排序8.2.4插入排序應用舉例

【例8.1】利用直接插入排序、折半插入排序和希爾排序對關鍵字為(56,22,67,32,59,12,89,26,48,37)的元素序列進行排序。【分析】主要考察直接插入排序、折半插入排序和希爾排序的算法思想。8.3.1簡單選擇排序簡單選擇排序是一種簡單的選擇類排序算法,它是通過依次找到待排序元素序列中最小的數(shù)據(jù)元素,并將其放在序列的最前面,從而使待排序元素序列變?yōu)橛行蛐蛄小K幕舅惴ㄋ枷朊枋鋈缦拢杭僭O待排序的元素序列有n個,在第一趟排序過程中,從n個元素序列中選擇最小的元素,并將其放在元素序列的最前面即第一個位置。在第二趟排序過程中,從剩余的n-1個元素中,選擇最小的元素,將其放在第二個位置。依次類推,直到?jīng)]有待比較的元素,簡單選擇排序算法結束。8.3選擇排序簡單選擇排序的算法描述如下。voidSelectSort(SqList*L,intn)/*簡單選擇排序*/{ inti,j,k; DataTypet; /*將第i個元素的關鍵字與后面[i+1...n]個元素的關鍵字比較,將關鍵字最小的的元素放在第i個位置*/ for(i=1;i<=n-1;i++) { j=i; for(k=i+1;k<=n;k++) /*關鍵字最小的元素的序號為j*/ if(L->data[k].key<L->data[j].key) j=k; if(j!=i) /*如果序號i不等于j,則需要將序號i和序號j的元素交換*/ { t=L->data[i]; L->data[i]=L->data[j]; L->data[j]=t; } }}8.3選擇排序8.3選擇排序

給定一組元素序列,其元素的關鍵字為(56,22,67,32,59,12,89,26),簡單選擇排序的過程如圖8.10所示。8.3.2堆排序1.什么是堆和堆排序堆排序(heapsort)是利用了二叉樹的樹形結構進行排序。所謂堆,排序的算法思想:堆排序主要是利用了二叉樹的樹形結構,按照完全二叉樹的編號次序,將元素序列的關鍵字依次存放在相應的結點。然后從葉子結點開始,從互為兄弟的兩個結點中(沒有兄弟結點除外),選擇一個較大(或較小)者與其雙親結點比較,如果該結點大于(或小于)雙親結點,則將兩者進行交換,使較大(或較小)者成為雙親結點。將所有的結點都做類似操作,直到根結點為止。這時,根結點的元素值的關鍵字最大(或最?。?.3選擇排序堆中的每一個結點都大于(或小于)其孩子結點。堆的數(shù)學形式定義為:假設存在n個元素,其關鍵字序列為(k1,k2,…,ki,…,kn),如果有:如果將這些元素的關鍵字存放在一維數(shù)組中,將此一維數(shù)組中的元素與完全二叉樹一一對應起來,則完全二叉樹中的每個非葉子結點的值都不小于(或不大于)孩子結點的值。8.3選擇排序

在堆中,堆的根結點元素值一定是所有結點元素值的最大值或最小值。例如,序列(87,64,53,51,23,21,48,32)和(12,35,27,46,41,39,48,55,89,76)都是堆,相應的完全二叉樹表示如圖8.11所示。8.3選擇排序如果將堆中的根結點(堆頂)輸出之后,然后將剩余的n-1個結點的元素值重新建立一個堆,則新堆的堆頂元素值是次大(或次小)值,將該堆頂元素輸出。然后將剩余的n-2個結點的元素值重新建立一個堆,反復執(zhí)行以上操作,直到堆中沒有結點,就構成了一個有序序列,這樣的重復建堆并輸出堆頂元素的過程稱為堆排序。8.3選擇排序2.建堆堆排序的過程就是建立堆和不斷調整使剩余結點構成新堆的過程。假設將待排序的元素的關鍵字存放在數(shù)組a中,第1個元素的關鍵字a[1]表示二叉樹的根結點,剩下的元素的關鍵字aa[2…n]分別與二叉樹中的結點按照層次從左到右一一對應。例如,a[1]的左孩子結點存放在a[2]中,右孩子結點存放在a[3]中,a[i]的左孩子結點存放在a[2*i]中,右孩子結點存放在a[2*i+1]中。8.3選擇排序

例如,給定一組元素,其關鍵字序列為(21,47,39,58,39,57,48,62),建立大頂堆的過程如圖8.12所示。結點的旁邊為對應的序號。建立后的大頂堆,其非葉子結點的元素值均不小于左、右子樹結點的元素值。8.3選擇排序建立大頂堆的算法描述如下所示。voidCreateHeap(SqList*H,intn)/*建立大頂堆*/{ inti; for(i=n/2;i>=1;i--) /*從序號n/2開始建立大頂堆*/ AdjustHeap(H,i,n);}8.3選擇排序voidAdjustHeap(SqList*H,ints,intm)/*調整H.data[s...m]的關鍵字,使其成為一個大頂堆*/{ DataTypet; intj; t=(*H).data[s]; /*將根結點暫時保存在t中*/ for(j=2*s;j<=m;j*=2) { if(j<m&&(*H).data[j].key<(*H).data[j+1].key) /*沿關鍵字較大的孩子結點向下篩選*/ j++; /*j為關鍵字較大的結點的下標*/ if(t.key>(*H).data[j].key)/*如果孩子結點的值小于根結點的值,則不進行交換*/ break; (*H).data[s]=(*H).data[j]; s=j; } (*H).data[s]=t; /*將根結點插入到正確位置*/}8.3選擇排序3.調整堆具體實現(xiàn):當堆頂元素輸出后,可以將堆頂元素放在堆的最后,即將第1個元素與最后一個元素交換a[1]<->a[n],則需要調整的元素序列就是a[1…n-1]。從根結點開始,如果其左、右子樹結點元素值大于根結點元素值,選擇較大的一個進行交換。即如果a[2]>a[3],則將a[1]與a[2]比較,如果a[1]>a[2],則將a[1]與a[2]交換,否則不交換。如果a[2]<a[3],則將a[1]與a[3]比較,如果a[1]>a[3],則將a[1]與a[3]交換,否則不交換。重復執(zhí)行此操作,直到葉子結點不存在,就完成了堆的調整,構成了一個新堆。8.3選擇排序8.3選擇排序

例如,一個大頂堆的關鍵字序列為(87,64,53,51,23,21,48,32),當輸出87后,調整剩余的關鍵字序列為一個新的的大頂堆的過程如圖8.13所示。。8.3選擇排序調整堆的算法實現(xiàn)如下。voidHeapSort(SqList*H)/*對順序表H進行堆排序*/{ DataTypet; inti; CreateHeap(H,H->length); /*創(chuàng)建堆*/ for(i=(*H).length;i>1;i--) /*將堆頂元素與最后一個元素交換,重新調整堆*/ { t=(*H).data[1]; (*H).data[1]=(*H).data[i]; (*H).data[i]=t; AdjustHeap(H,1,i-1); /*將(*H).data[1..i-1]調整為大頂堆*/ }}8.4交換排序8.4.1冒泡排序冒泡排序(bubblesort)是一種簡單的交換類排序算法,它是通過交換相鄰的兩個數(shù)據(jù)元素,逐步將待排序序列變成有序序列。它的基本算法思想描述如下:假設待排序元素有n個,從第1個元素開始,依次交換相鄰的兩個逆序元素,直到最后一個元素為止。當?shù)?趟排序結束,就會將最大的元素移動到序列的末尾。然后按照以上方法進行第2趟排序,次大的元素將會被移動到序列的倒數(shù)第2個位置。依次類推,經(jīng)過n-1趟排序后,整個元素序列就成了一個有序的序列。每趟排序過程中,值小的元素向前移動,值大的元素向后移動,就像氣泡一樣向上升,因此將這種排序方法稱為冒泡排序。8.4交換排序

例如,一組元素序列的關鍵字為(56,22,67,32,59,12,89,26,48,37),對該關鍵字序列進行冒泡排序,第一趟排序過程如圖8.15所示。8.4交換排序

從圖8.15容易看出,第一趟排序結束后,關鍵字最大的元素被移動到序列的末尾。按照這種方法,冒泡排序的全過程如圖8.16所示。8.4交換排序冒泡排序的算法描述如下。voidBubbleSort(SqList*L,intn)/*冒泡排序*/{ inti,j,flag; DataTypet; for(i=1;i<=n-1&&flag;i++) /*需要進行n-1趟排序*/ { flag=0; for(j=1;j<=n-i;j++) /*每一趟排序需要比較n-i次*/ if(L->data[j].key>L->data[j+1].key)

{ t=L->data[j]; L->data[j]=L->data[j+1]; L->data[j+1]=t; flag=1;

} }}8.4交換排序8.4.2快速排序快速排序的算法思想是:從待排序記錄序列中選取一個記錄(通常是第一個記錄)作為樞軸,其關鍵字設為key,然后將其余關鍵字小于key的記錄移至前面,而將關鍵字大于key的記錄移至后面,結果將待排序記錄序列分為兩個子表,最后將關鍵字key的記錄插入到其分界線的位置。我們將這個過程稱為一趟快速排序。通過這一趟劃分后,就以關鍵字為key的記錄為界,將待排序序列分為兩個子表,前面的子表所有記錄的關鍵字均不大于key,而后面子表的所有記錄的關鍵字均不小于key。繼續(xù)對分割后的子表進行上述劃分,直至所有子表的表長不超過1為止,此時的待排序記錄就成了一個有序序列。9.4交換排序【算法步驟】設待排序序列存放在數(shù)組a[1…n]中,n為元素個數(shù),設置兩個指針i和j,初值分別為1和n,令a[1]作為樞軸元素賦給pivot,a[1]相當于空單元,然后執(zhí)行以下操作:(1)j從右往左掃描,若a[j].key<pivot.key,將a[j]移至a[i]中,此時a[j]相當于空單元,并執(zhí)行一次i++操作;(2)i從左至右掃描,直至a[i].key>pivot.key,將a[i]移至a[j]中,并執(zhí)行一次j--操作;(3)重復執(zhí)行(1)和(2),直到出現(xiàn)i≥j,則將元素pivot移動到a[i]中。此時整個元素序列在位置i被劃分成兩個部分,前一部分的元素關鍵字都小于a[i].key,后一部分元素的關鍵字都大于等于a[i].key。即完成了一趟快速排序。8.4交換排序

例如,一組元素序列的關鍵字為(37,19,43,22,22,89,26,92),根據(jù)快速排序算法思想,第一次劃分的過程如圖8.17所示。8.4交換排序

從圖8.17容易看出,當一趟快速排序完畢之后,整個元素序列被樞軸的關鍵字37劃分為兩個部分,前一個部分的關鍵字都小于37,后一部分元素的關鍵字都大于等于37。其實,快速排序的過程就是以樞軸為中心將元素序列劃分的過程,直到所有的序列被劃分為單獨的元素,快速排序完畢。8.4交換排序intPartition(SqList*L,intlow,inthigh)/*對順序表L.r[low..high]的元素進行一趟排序*/{DataTypet;KeyTypepivotkey; pivotkey=(*L).data[low].key;/*將表的第一個元素作為樞軸元素*/ t=(*L).data[low]; while(low<high) /*從表的兩端交替地向中間掃描*/ { while(low<high&&(*L).data[high].key>=pivotkey) high--; if(low<high) /*將當前high指向的元素保存在low位置*/ { (*L).data[low]=(*L).data[high]; low++; }while(low<high&&(*L).data[low].key<=pivotkey) /*從表的始端向后掃描*/ low++; if(low<high) /*將當前l(fā)ow指向的元素保存在high位置*/ { (*L).data[high]=(*L).data[low]; high--; }

}(*L).data[low]=t;/*將樞軸元素保存在low=high的位置*/ returnlow; /*返回樞軸所在位置*/}8.4交換排序8.4交換排序voidQuickSort(SqList*L,intlow,inthigh)/*對順序表L進行快速排序*/{ intpivot; if(low<high) /*如果元素序列的長度大于1*/ { pivot=Partition(L,low,high); /*將待排序序列L.r[low..high]劃分為兩部分*/ QuickSort(L,low,pivot-1); /*對左邊的子表進行遞歸排序,pivot是樞軸位置*/ QuickSort(L,pivot+1,high); /*對右邊的子表進行遞歸排序*/ }}8.4交換排序

快速排序在最好的情況下是每趟排序將序列一分兩半,從表中間開始,將表分成兩個大小相同的子表,類似折半查找,這樣快速排序的劃分的過程就將元素序列構成一個完全二叉樹的結構,分解的次數(shù)等于樹的深度即log2n,因此快速排序總的比較次數(shù)為T(n)≤n+2T(n/2)≤n+2*(n/2+2*T(n/4))=2n+4T(n/4)≤3n+8T(n/8)≤…≤nlog2n+nT(1)。因此,在最好的情況下,時間復雜度為O(nlog2n)。8.4.3交換排序應用舉例【例8.2】一組元素的關鍵字序列為(37,22,43,32,19,12,89,26,48,92),使用冒泡排序和快速排序對該元素進行排序,并輸出冒泡排序和快速排序的每趟排序結果?!痉治觥恐饕疾靸煞N交換排序即冒泡排序和快速排序的算法思想。這兩種算法都是對存在逆序的元素進行交換,從而實現(xiàn)排序。主要區(qū)別在于:冒泡排序通過比較相鄰的兩個元素,并對兩個相鄰的逆序元素進行交換;而快速排序則是選定一個樞軸元素作為參考元素,設置兩個指針,分別從表頭和表尾開始,將當前掃描的元素與樞軸元素進行比較,存在逆序的元素不一定是相鄰的元素,如果存在逆序,則交換之。8.3交換排序8.5歸并排序

歸并排序(MergingSort)的基本思想是:將兩個或兩個以上的元素有序序列組合,使其成為一個有序序列。其中最為常用的是2路歸并排序。2路歸并排序的主要思想是:假設元素的個數(shù)是n,將每個元素作為一個有序的子序列,然后將相鄰的兩個子序列兩兩歸并,得到個長度為2的有序子序列。然后將相鄰的兩個有序子序列兩兩歸并,得到個長度為4的有序子序列。如此重復,直至得到一個長度為n的有序序列為止。8.5歸并排序voidMerge(DataTypes[],DataTypet[],intlow,intmid,inthigh)/*將有序的s[low...mid]和s[mid+1..high]歸并為有序的t[low..high]*/{ inti,j,k; i=low,j=mid+1,k=low; while(i<=mid&&j<=high) /*將s中元素由小到大地合并到t*/ { if(s[i].key<=s[j].key) { t[k]=s[i++]; } else { t[k]=s[j++]; } k++; } while(i<=mid) /*將剩余的s[i..mid]復制到t*/ t[k++]=s[i++]; while(j<=high) /*將剩余的s[j..high]復制到t*/ t[k++]=s[j++];}8.5歸并排序voidMergeSort(DataTypes[],DataTypet[],intlow,inthigh)/*2路歸并排序,將s[low...high]歸并排序并存儲到t[low...high]中*/{ intmid; DataTypet2[MaxSize]; if(low==high) t[low]=s[low]; else { mid=(low+high)/2; /*將s[low...high]分為s[low...mid]和s[mid+1...high]*/ MergeSort(s,t2,low,mid); /*將s[low...mid]歸并為有序的t2[low...mid]*/ MergeSort(s,t2,mid+1,high); /*將s[mid+1...high]歸并為有序的t2[mid+1...high]*/ Merge(t2,t,low,mid,high); /*將t2[low...mid]和t2[mid+1..high]歸并到t[low...high]*/ }}8.6基數(shù)排序基數(shù)排序是一種與前面所述各種排序方法完全不同的方法,前面的排序主要通過對元素的關鍵字進行比較和移動記錄這兩種操作,而實現(xiàn)基數(shù)排序則不需要進行對關鍵字比較。

例如,一組元素序列的關鍵字為(334,45,21,467,821,562,342,45)。這組關鍵字位數(shù)最多的是3位,在排序之前,首先將所有的關鍵字都看作是一個3位數(shù)字組成的數(shù),即(324,285,021,467,821,562,342,045)。對這組關鍵字進行基數(shù)排序需要進行3趟分配和收集。首先需要對該關鍵字序列的最低位進行分配和搜集,然后對十位數(shù)字進行分配和收集,最后是對最高位的數(shù)字進行分配和收集。一般情況下,采用鏈表實現(xiàn)基數(shù)排序。8.6基數(shù)排序

一般情況下,采用鏈表實現(xiàn)基數(shù)排序。對最低位進行分配和收集的過程如圖8.21所示。其中,數(shù)組f[i]保存第i個鏈表的頭指針,數(shù)組r[i]保存第i個鏈表的尾指針。

對十位數(shù)字分配和收集的過程如圖8.22所示。

8.6基數(shù)排序對百位數(shù)字分配和收集的過程如圖8.23所示。

經(jīng)過第一趟排序即對個位數(shù)作為關鍵字進行分配后,關鍵字被分為9類,個位數(shù)字相同的數(shù)字被劃分為一類,然后對分配后的關鍵字進行收集之后,得到以個位數(shù)字非遞減排序的序列。同理,經(jīng)過第二趟分配和收集后,得到以十位數(shù)字非遞減排序的序列。經(jīng)過第三趟分配和收集后,得到最終的排序結果。8.6基數(shù)排序基數(shù)排序的算法主要包括分配和收集。#defineMaxNumKey6/*關鍵字項數(shù)的最大值*/#defineRadix10 /*關鍵字基數(shù),此時是十進制整數(shù)的基數(shù)*/#defineMaxSize1000typedefintKeyType;typedefstruct{ KeyTypekey[MaxNumKey];/*關鍵字*/ intnext;}SListCell; /*靜態(tài)鏈表的結點類型*/typedefstruct{ SListCelldata[MaxSize]; /*存儲元素,data[0]為頭結點*/ intkeynum; /*每個元素的當前關鍵字個數(shù)*/ intlength; /*靜態(tài)鏈表的當前長度*/}SList; /*靜態(tài)鏈表類型*/typedefintaddr[Radix]; /*指針數(shù)組類型*/8.6基數(shù)排序基數(shù)排序的分配算法實現(xiàn)如下所示。voidDistribute(SListCelldata[],inti,addrf,addrr)/*為data中的第i個關鍵字key[i]建立Radix個子表,使同一子表中元素key[i]相同*//*f[0..Radix-1]和r[0..Radix-1]分別指向各個子表中第一個和最后一個元素*/{ intj,p; for(j=0;j<Radix;j++) /*將各個子表初始化為空表*/ f[j]=0; for(p=data[0].next;p;p=data[p].next) { j=trans(data[p].key[i]); /*將對應的關鍵字字符轉化為整數(shù)類型*/ if(!f[j]) /*f[j]是空表,則f[j]指示第一個元素*/ f[j]=p; else da

溫馨提示

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

評論

0/150

提交評論