歸併排序C語言實現與分析

具體代碼

#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.最後注意我們是把數組先有序地謄到一個空的數組裏了,還要放回來,完成。

性能分析

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章