說明
之前所介紹的排序法都是在同一個陣列中的排序,考慮今日有兩筆或兩筆以上的資料,它可能是不同陣列中的資料,或是不同檔案中的資料,如何爲它們進行排序?
解法
可以使用合併排序法,合併排序法基本是將兩筆已排序的資料合併並進行排序,如果所讀入的資料尚未排序,可以先利用其它的排序方式來處理這兩筆資料,然後再將排序好的這兩筆資料合併。有人問道,如果兩筆資料本身就無排序順序,何不將所有的資料讀入,再一次進行排序?排序的精神是儘量利用資料已排序的部份,來加快排序的效率,小筆資料的排序較爲快速,如果小筆資料排序完成之後,再合併處理時,因爲兩筆資料都有排序了,所有在合併排序時會比單純讀入所有的資料再一次排序來的有效率。
那麼可不可以直接使用合併排序法本身來處理整個排序的動作?而不動用到其它的排序方式?
答案是肯定的,只要將所有的數字不斷的分爲兩個等分,直到最後剩一個數字爲止,然後再反過來不斷的合併,就如下圖所示:
不過基本上分割又會花去額外的時間,不如使用其它較好的排序法來排序小筆資料,再使用合併排序來的有效率。下面的程序範例,使用的是快速排序法來處理小筆資料排序,然後再使用合併排序法處理合並的動作。
代碼:
//這個快速排序法的概念,它以最右邊的值s作比較的標準,將整個數列分爲三個部份,
//一個是小於s的部份,一個是大於s的部份,一個是未處理的部份
int partition(int number[],int left, int right) //尋找軸所在的正確位置
{
int i,j,s;
int temp;
s = number[right];
i = left - 1;
j = left;
for(j=left;j<right;++j)
{
if(number[j] <= s)
{
++i;
temp = number[i];
number[i] = number[j];
number[j] = temp;
}
}
temp = number[i+1];
number[i+1] = number[right];
number[right] = temp;
return i+1;
}
void quicksort3(int number[], int left, int right)
{
int q;
if(left < right)
{
q = partition(number,left,right);
quicksort3(number,left,q-1);
quicksort3(number,q+1,right);
}
}
//合併排序,各獨立文件採用快速排序排好序
void mergesort(int number1[],int M,int number2[],int N,int number3[])
{
int i,j,k;
i = 0; j = 0; k = 0;
while(i < M && j < N)
{
if(number1[i] <= number2[j])
number3[k++] = number1[i++];
else
number3[k++] = number2[j++];
}
while(i < M)
number3[k++] = number1[i++];
while(j < N)
number3[k++] = number2[j++];
}