第四章 系統實作
4.1 教學單元介紹
例如輸入為:21,3,13,25,9 第 1 次執行結果:3,13,21,9,25 第 2 次執行結果:3,13,9,21,25 第 3 次執行結果:3,9,13,21,25 第 4 次執行結果:3,9,13,21,25
HEAP-SORT 說明
堆積排序是利用堆積的特性完成資料的排序,假設檔案有 n 個記錄 R1,R2,...Rn,其鍵值分別為 K1,K2....,Kn。
由於堆積是一個完整的二元樹,首先依序將記錄放入以建立一 個完整二元樹。為了利用堆積排序將資料由小到大排序,我們 可以將堆積排序的步驟大致上分為以下 4 點:
1.將所有紀錄依序加入建成一個完整二元樹。
2.將完整二元樹調整成最大堆積樹。
3.將樹根跟最後一個節點的位置對調,並且扣除原樹根節點 以外的完整二元樹並調整為最大堆積樹。
重複本步驟,直到最大堆積樹中已沒有任一節點。
4.最後依序印出儲存最大堆積樹的陣列的每個元素值,便可 以得到由小到大排序後的結果。
1. 副程式 Adjust 的過程是先以 root 所指的樹根和它的兩個子 節點中最大者相比,若較子節點大則不必調整,若較子節點 小則將較大的子節點移至樹根的位置,並繼續與下一層的子 節點比較,重複這個步驟直到子節點比它小為止,此時才將 原來的樹根節點放到合適的位置上。
2.主程式中,剛開始的第一個 for 迴圈即是將完整二元樹調整 為最大堆積樹。而調整方式是:由右而左,由下而上逐層調整
每個子樹,最後使整個樹變成最大堆積樹,首先調整以最後一
void Heap sort(Element *list,const int n) { for(int n/2;i>=1;i--)
void adjust(Element *tree,const int root,const int n) { Element e=tree[root];
int k=e.getKey();
for(int j=2*root;j<=n;j*=2){
if(j<n)
if(tree[j].getKey()<tree[j+1].getKey())j++;
if(k>=tree[j].getKey())break;
第 6 次執行結果:19,26,48,59,61,77 第 7 次執行結果:15,19,26,48,59,61,77 第 8 次執行結果:11,15,19,26,48,59,61,77 第 9 次執行結果:5,11,15,19,26,48,59,61,77 第 10 次執行結果:1,5,11,15,19,26,48,59,61,77
INSERTION-SORT 說明
所謂的插入排序簡單的說就像我們在玩撲克牌時,整理手
void insertion-sort(element list[],int n) { int i,j;
圖 4-3 INSERTION-SORT 程式碼
例如輸入為:23,12,6,43,31 第 1 次執行結果:6,23,12,43,31 第 2 次執行結果:6,12,23,43,31 第 3 次執行結果:6,12,23,31,43 第 4 次執行結果:6,12,23,31,43
MERGE-SORT 說明
合併排序簡單的說就是將兩個已經排序好檔案(X1,
X2...Xm)和(Xm+1,Xm+2...Xn)合併成另一個檔案(Y1,
Y2...Yn)。合併排序中最常用的就是 2-way merge sort,
每次將相鄰的兩個檔案合併成一個排序好的檔案。首先將檔案
void merge(element list[],element sorted[],int i,int n,int m) {
int t,j,k; j=m+1; k=i;
while(i<=m&&j<=n){
if(list[i].key<=list[j].key)
第 1 次執行結果:5,26,1,77,11,61,15,59,19,48 第 2 次執行結果:1,5,26,77,11,15,59,61,19,48 第 3 次執行結果:1,5,11,15,26,59,61,77,19,48 第 4 次執行結果:1,5,11,15,19,26,48,59,61,77
QUICK-SORT 說明
快速排序是具有最佳平均執行時間的排序方法。在 n 個記 錄 R1,R2,...,Rn 中,將 Ri 放在 s(i)的位置,使得若 j<s(i),則 Kj□Ks(i);若 j>s(i),則 Kj□ Ks(i),也就是將 Ri 左邊的鍵值都小於 Ki,而在 Ri 右邊的鍵值大於 Ki,這就是
(R1,R2,...Rs(i)-1) Rs(i) (Rs(i)+1,...Rn) 分隔後 Rs(i)的位置是相對於整個檔案來說是正確的,不需在
void quicksort(element list[], int left, int right,) { int pivot,i,j;
do i++; 第 1 次執行結果:11,5,19,1,15,26,59,61,48,37 第 2 次執行結果:1,5,11,19,15,26,59,61,48,37 第 3 次執行結果:1,5,11,19,15,26,59,61,48,37 第 4 次執行結果:1,5,11,15,19,26,59,61,48,37 第 5 次執行結果:1,5,11,15,19,26,48,37,59,61 第 6 次執行結果:1,5,11,15,19,26,37,48,59,61 第7 次執行結果:1,5,11,15,19,26,37,48,59,61
RADIX-SORT 說明
多鍵排序就是把數個鍵的紀錄排序起來,這些鍵是 K1,
K2,...Kr(其中 K1 為第一優先的鍵,而 Kr 是最後的鍵)。一 個記錄的串列為 R1,R2,....Rn 被稱為根據鍵 K1,K2...Kr 排列結果。而多鍵排序又可分為最高有效數字排序(MSD),最低 有效數字排序(LSD),而這兩個方法只是定義各鍵值的排序不同 而已,LSD 和 MSD 排序可以用來排序只有一個鍵的紀錄。對於 這點,就是將該鍵分成數個鍵,舉例來說:如果原來鍵是一個
數字,那們鍵中的每一個位數可以視為一個鍵。所以當鍵值在 0 到 999 之間的話,我們就可以利用 LSD 和 MSD 對三個鍵 K1,
K2,K3 做排序,其中 K1 是百位數,K2 是十位數,K3 是個位數。
而每個鍵的範圍是由 0 到 9,所以每個鍵都可以用十個櫃子的 櫃子排序。在基數排序(radix sort)中,我們根據一個基底 RADIX_SIZE 將鍵值分解成數個數字。當 RADIX_SIZE=10 時,我 們可以得到上述的十進位分解。在一個基底 RADIX_SIZE 排序 中,所需的櫃子數為 RADIX_SIZE 個。假 設要排序的紀錄是 R1,....,Rn 而它們的鍵值被一個基底 RADIX_SIZE 所分解,
對每個第 MAX_DIGIT 為數的鍵,其範圍從 0 到 RADIX_SIZE-1,
所以我們需要 RADIX_SIZE 個櫃子。假設每個記錄包含一個 link 欄位,每個櫃子中的紀錄會被連結起來成一條鏈且存在
front[i],其中 0□i□r,是指向每條櫃子中的鏈之第一個記 錄的指標,以及 rear[i]是指向櫃子中最後一個紀錄的指標,
這些鏈會佇列來處理。而範例的這個動畫是以 LSD 的方式處 理。主要程式碼如圖 4-6 圖所示。
list_pointer radix_sort(list_pointer ptr) { list_pointer front[RADIX_SIZE]
,rear[RADIX_SIZE];
int i,j,digit;
for(i=MAX_DIGIT-1;i>=0;i--){
for(j=0;j<RADIX_SIZE;j++)
第 1 次執行結果:
SELECTION-SORT 說明
選擇排序簡單的說就是找出剩餘記錄中鍵值最小的紀錄。
void selectionsort (int list[],int last) {
int current,samllest,holddata,walker;
for(current=0;current<last;current++) {
smallest=current;
for(walker=current+1;walker<=last;walker++) if(list[walker]<list[smallest])
圖 4-7 SELECTION-SORT 程式碼
例如輸入為:23,78,45,8,32,56
第 1 次執行結果:8,78,45,23,32,56 第 2 次執行結果:8,23,45,78,32,56 第 3 次執行結果:8,23,32,78,45,56 第 4 次執行結果:8,23,32,45,78,56 第 5 次執行結果:8,23,32,45,56,78
SHELL-SORT 說明
謝爾排序法的主要精神是首先將整個陣列分成若干個陣 接插入排序,完成後再以 dn-1 的組距重新排序(dn-1<dn),使 得每一組的資料變多一點,而且組別變少,重覆分組及排序,
直到 d0=1,使得所有元素屬於同一組為止。主要程式碼如圖 4-8 圖所示。
void shellsort(int list[],int last) {
int hold,incre,curr,walker;
incre=last/2;
while(walker>=0&&hold<list[walker]) {
return;
}
圖 4-8 SHELL-SORT 程式碼
例如輸入為:77,62,14,9,30,21,80,25 第 1 次執行結果:30,21,14,9,77,62,80,25 第 2 次執行結果:14,9,30,21,77,25,80,62 第 3 次執行結果:9,14,21,25,30,62,77,80