經典算法(五)----歸併排序----圖解法讓你快速入門

引言

     只要設計到數據,就會涉及到數據的排序問題,比如給你隨機給你五個整數  3,1,5,2,4 。讓你從小到大進行排序,那我們該怎樣纔是實現對這些整數的排序呢 ?

    答案是多種多樣的,比如用插入排序、希爾排序、堆排序、歸併排序、快速排序等等,這些排序方法都可以實現對整數排序,而這篇文章要講的就是歸併排序

本文將從以下幾個問題對歸併排序進行分析和講解:

  1. 什麼是歸併排序?
  2. 歸併排序的大概過程是什麼?
  3. 怎樣用代碼實現歸併排序?
  4. 歸併排序的代碼詳解。

 

什麼是歸併排序?

下面看百度百科對歸併排序的定義:

歸併排序(MERGE-SORT)是建立在歸併操作上的一種有效的排序算法,該算法是採用分治法(Divide and Conquer)的一個非常典型的應用。將已有序的子序列合併,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合併成一個有序表,稱爲二路歸併。歸併排序是一種穩定的排序方法。

簡單理解:歸併排序一個分兩大部,第一步分,第二步合。

下面先看一個動圖:

 

歸併排序的大概過程是什麼?

我們用歸併排序講一個例子來說明,要排序的數組爲3,1,5,2,4.

歸併排序第一步:分

分採取一份爲二的方法(所以這個歸併排序又叫二路歸併排序)

mid=(first+last)/2(first是最左邊,last是最右邊),採取前面的公式,分爲【first,mid】和【mid+1,last】

如上圖所示,直到分成一個一個的數,分的話可以採取遞歸調用的方法。

再看第二大步:合

合是指把兩個數組合成一個數組,而且合成之後數組是有序的。

合成方法:在合成過程中需要一個臨時數組來存合成的結果。可以定義兩個變量 i 和 j  分別指向兩個數組的第一個元素,比較他倆誰小。就是那個對應的元素放到臨時數組裏面,指向數組的變量後移。只要其中一個變量走到頭位置。

如果是其中一個走到頭了,但是另一個還未到頭,這時候就需要把數組剩餘的元素放到臨時數組裏面。

上面說的是把兩個數組合二爲一,但是兩個數組其實是一個數組中兩塊不同的部分(用下標區分的),等上面合成結束,就把臨時數組放到原數組裏面,下面看合代碼。

//將兩個有序數列a[first...mid]和a[mid...last]合併
void MergeArray(int a[],int first,int mid,int last,int temp[])
{
	int i=first, j=mid+1;
	int m=mid  , n=last;
	int k=0;
	
	while(i<=m&&j<=n)
	{
		if(a[i]<=a[j])
			temp[k++]=a[i++];
		else
			temp[k++]=a[j++];
	}
	
	while(i<=m)
		temp[k++]=a[i++];
		
	while(j<=n)
		temp[k++]=a[j++];
		
	for(i=0;i<k;i++)
		a[first+i]=temp[i];
} 

  怎樣用代碼實現歸併排序?

下面看完成的代碼

#include<iostream>
using namespace std;

//將兩個有序數列a[first...mid]和a[mid...last]合併
void MergeArray(int a[],int first,int mid,int last,int temp[])
{
	int i=first, j=mid+1;
	int m=mid  , n=last;
	int k=0;
	
	while(i<=m&&j<=n)
	{
		if(a[i]<=a[j])
			temp[k++]=a[i++];
		else
			temp[k++]=a[j++];
	}
	
	while(i<=m)
		temp[k++]=a[i++];
		
	while(j<=n)
		temp[k++]=a[j++];
		
	for(i=0;i<k;i++)
		a[first+i]=temp[i];
} 

//歸併排序函數    穩定 
void MergeSort(int a[],int first,int last,int temp[])
{
	if(first<last)
	{
		int mid=(first+last)/2;
		MergeSort(a,first,mid,temp);
		MergeSort(a,mid+1,last,temp);
		MergeArray(a,first,mid,last,temp);
	}
}
//輸出數組的值
void printf(int arr[],int len)
{
	for(int i=0;i<len;i++)
		cout<<arr[i]<<" "; 
	cout<<endl;
}
int main()
{
	//要排序的數組 
	int arr[]={3, 44,38, 5,47,15,36,26,27,2 ,46,4 ,19,50,48};
	int len=15;//要排序的數組長度 
	int temp[1];
	//排序 
	MergeSort(arr,0,len-1,temp);
	
	//輸出 
	printf(arr,len);
	return 0;
}

運行結果:

 

歸併排序代碼詳解

  1. 第一步分,首先要知道怎樣分,採取的是遞歸調用,記得注意遞歸的結束條件
  2. 第二步合,把兩個小數組合成一個大數組,合的過程應該是啥,一定要清楚

本文參考以及引用:

百度百科

圖片動畫
 

 

 

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