接著上篇文章歸併排序(遞迴)來**下,歸併排序的非遞迴實現。
歸併排序的非遞迴實現:
(1)將兩個相鄰的有序序列歸併成乙個有序序列,我們稱為「一次歸併」。
(2)「一趟歸併」,是多次執行「一次歸併」的結果。在「一趟歸併」中,除最後乙個有序序列外,其他有序序列中記錄的個數(稱為序列長度)相同,用h表示。現在的任務是把若干個相鄰的長度為h的有序序列和最後乙個長度有可能小於h的有序序列進行兩兩歸併,把結果存放到temp[1]~temp[n]中(注意:我們是從下標1開始存放排序序列的)。為此,設引數i,指向待歸併序列的第乙個記錄,初始時,i=1,顯然歸併的步長應是2h。在歸併過程中,有以下三種情況:
<1> 若 i <= n - 2h + 1,則表示待歸併的兩個相鄰有序序列的長度均為h,執行「一次歸併」,完成後i加2h,準備進行下一次「一次歸併」。
<2> 若 i < n - h + 1,則表示仍有兩個相鄰有序序列,乙個長度為h,另乙個長度小於h,則執行這兩個有序序列的歸併,完成後退出「一趟歸併『。
<3> 若 i >= n - h + 1,則表明只剩下乙個有序序列,直接將該有序序列送到temp陣列的相應位置,完成後退出」一趟排序「。
綜上,」一趟歸併排序「的演算法如下:
(3)如何控制「二路歸併排序的非遞迴實現」的結束?開始時,有序序列的長度為1,結束時,有序序列的長度為n,因此,可以用有序序列的長度來控制排序過程的結束。演算法如下:void mergepass(int arr, int n, int h, int temp) // 從下標1開始存放待排序序列
if (i < n - h + 1) // 此時 n - 2*h + 1 < i < n - h + 1,待歸併序列中有乙個長度小於h。
mergearray(arr, i, i + h - 1, n, temp);
else
// 此時 i >= n - h + 1,待歸併序列中只剩乙個子串行。
for (int k = i; k <= n; k++)
temp[k] = arr[k];
}
完整**如下:void mergesort2(int arr, int n, int temp) // 從下標1開始存放待排序序列
}
#include
// 將2個相鄰的有序陣列arr[first...mid]和arr[mid+1...last]歸併成乙個有序陣列temp[first, last]。
// 這是二路歸併的核心操作,在歸併過程中,可能會破壞原來的有序序列,所以,將歸併的結果存入另外乙個陣列(temp)中。
void mergearray(int arr,int first,int mid,int last, int temp)
while (i <= mid)
temp[k++] = arr[i++]; // 若經過上述迴圈後,arr[j]中的元素都取完,而arr[i]中還有剩餘元素,那麼將arr[i]中的元素順序的存入歸併後的有序陣列temp中。
while (j <= last)
temp[k++] = arr[j++]; // 若經過上述迴圈後,arr[i]中的元素都取完,而arr[j]中還有剩餘元素,那麼將arr[j]中的元素順序的存入歸併後的有序陣列temp中。
// 將排好序的臨時陣列重新放置到原陣列arr中
for (i = 0;i < k;i++)
arr[first+i] = temp[i];
}void mergepass(int arr, int n, int h, int temp) // 從下標1開始存放待排序序列
if (i < n - h + 1) // 此時 n - 2*h + 1 < i < n - h + 1,待歸併序列中有乙個長度小於h。
mergearray(arr, i, i + h - 1, n, temp);
else
// 此時 i >= n - h + 1,待歸併序列中只剩乙個子串行。
for (int k = i; k <= n; k++)
temp[k] = arr[k];
}// 如果想從下標0開始存放待排序序列,應對mergepass函式做如下修改。
//void mergepass(int arr, int n, int h, int temp)
////
// if (i < n - h)
// mergearray(arr, i, i + h - 1, n, temp);
// else
// for (int k = i; k <= n; k++)
// temp[k] = arr[k];
//}void mergesort2(int arr, int n, int temp) // 從下標1開始存放待排序序列
}// 使用歸併排序
void merges(int arr,int n)
int main(int argc, const
char * argv) ; // 注意:我們是從下標1開始存放待排序序列,也就是說1000不參與排序。
merges(arr, 10);
for(int i = 0;i < 10;i++) // 我們是從下標1開始存放待排序序列,所以列印時,下標的起始值為1。
printf("%d ",arr[i]);
printf("\n");
return
0;}
歸併排序(遞迴 非遞迴 自然歸併排序)
演算法思想 歸併排序是分治法的典型應用,其思想是不斷地將兩個有序的陣列合併為乙個有序陣列。遞迴實現 include void merge int a,int left,int m,int right void mergesortaux int a,int left,int right void me...
歸併排序 遞迴 非遞迴
首先簡單的介紹一下歸併演算法的核心思想 將我們將一組資料分成若干個組,即分到每組資料為1個元素的情況下就不用分了,然後在分別比較每兩組資料元素的大小,將其合併為一組資料再去和其他同等級別的組的資料元素取比較,然後合併到臨時的空間中然後在複製給原空間,依此類推,直到最後全部合併完畢,陣列就成為一組有序...
歸併排序 非遞迴
static void merging sort beta int a 歸併排序演算法 非遞迴 static void mergepass int source,int temp,int gap,int len if i len gap else static void merge beta int...