歸併排序(非遞迴)

2021-07-12 01:07:40 字數 2741 閱讀 7737

接著上篇文章歸併排序(遞迴)來**下,歸併排序的非遞迴實現。

歸併排序的非遞迴實現:

(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陣列的相應位置,完成後退出」一趟排序「。

綜上,」一趟歸併排序「的演算法如下:

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];

}

(3)如何控制「二路歸併排序的非遞迴實現」的結束?開始時,有序序列的長度為1,結束時,有序序列的長度為n,因此,可以用有序序列的長度來控制排序過程的結束。演算法如下:

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...