具體代碼
#include<stdio.h>
//將兩個有序數組合並的過程
void Merge(int* R, int start, int mid, int end)
{
//需要把元素全謄到這個新數組去
int A[end-start+1];
//i代表第一個有序數組的起始位置
int i = start;
//j代表第二個有序數組的起始位置
int j = mid+1;
//k用來逐個表示A數組中的元素
int k = 0;
//從這兩個有序數組中找出小的,逐個放入A數組
while(i<=mid && j<=end)
{
//j的小就放j
if(R[i]>R[j])
{
A[k] = R[j];
j++;
}
else
{
A[k] = R[i];
i++;
}
k++;
}
//當出現某個數組放完了之後,直接把另一個數組剩下的全放入A即可
//其實下面那兩個if可以不寫,只不過這裏只是增強可讀性而已....
if(i>mid)
{
while(j<=end)
{
A[k] = R[j];
j++;
k++;
}
}
if(j>end)
{
while(i<=mid)
{
A[k] = R[i];
i++;
k++;
}
}
//然後再把已經有序了的元素裝回到原來啊的R數組
for(int m = 0;m<k;m++)
{
R[start] = A[m];
start++;
}
}
//歸併排序
void MergeSort(int* R, int start, int end)
{
//如果沒把數組分到單個元素,就一直分治
if(start<end)
{
//一分爲二
int mid = (start+end)/2;
//左右兩邊排好序
MergeSort(R,start,mid);
MergeSort(R,mid+1,end);
//拼接到一起
Merge(R,start,mid,end);
}
}
int main()
{
int M[6] = {1,5,3,7,8,2};
MergeSort(M,0,5);
for(int i=0;i<6;i++)
{
printf("%d ", M[i]);
}
}
過程分析
這是馮諾依曼大佬提出的算法,利用了分治的思想,各層分治遞歸可以同時進行。所以我連分步解釋的圖都不好畫了。。。。。。
不過總體流程大概是這樣:
這個算法的主體思路就是把一個數組全部劃分成單個元素,單個元素進行比較後合併。由於是遞歸,多個比較同時發生,所以會更快。每次在比較完後,會得到兩個有序數組,只需要將有序數組合並即可(對於只用單個元素的情況,就是直接比大小了)。
我這裏就只講一下合併步驟的思路了。
合併步驟
1.得到兩個有序數組,但是他們在空間上是連在一起的,他們以你之前劃分的標準mid元素來分界。
2.所以兩個數組的空間位置分別是
start—mid, mid+1—end-1
準備好指針,開始排序即可
3.由於他們的都是有序數組,從頭逐個比較,取走小的那個即可。
比如:
A數組-----------1,6,7,9,9
B數組-----------2,3,4,5,8
那麼我們先從A中取走1,再比較A的第二個元素和B的第一個元素,取走2,同理,繼續比較,取走B中的3,然後4,然後5,然後再取A中的7,再取B中的。
4.這時,B數組已經取完了,只需要把剩下的A中的兩個9全部放到數組裏即可。
5.最後注意我們是把數組先有序地謄到一個空的數組裏了,還要放回來,完成。