歸並排序算法思想


歸並排序

這次我們來講述歸並排序的基本思想。

  • 歸並排序,首先把一個數組中的元素,按照某一方法,先拆分了之后,按照一定的順序各自排列,然后再歸並到一起,使得歸並后依然是有一定順序的 。
  • 歸並排序算法可以利用遞歸的思想或者迭代的思想去實現。首先我們先把一個無序的數組去拆分,然后利用一定的規則,去合並。類似於二叉樹的結構。其總的時間復雜度為O( n log n)。空間復雜度為 S(nlogn)

示例圖如下:

  • 首先我們看到,一個無序的數組如下,為了簡約,以及簡便解釋,我們定義了8個元素。

photo1

  • 然后,我們把該8個元素進行划分,分成左邊四個,和右邊四個,如下圖。

photo2

  • 依次按照上邊的方法,把剩余的數組繼續拆分,一直拆到只剩下一個元素的時候,停止。如下圖

photo3

  • 由於存在8個單獨的子元素,然后我們兩兩把元素合並,並且按照一定順序排序(此處用從小到大的順序排序)。如下圖:

photo4

  • 此時,我們可以看到我們又得到了四個不同顏色的數組,並且在這個數組里邊,也是按照一定的順序排好序的。隨后,繼續利用這種方法,把剩余的繼續合並,一直合並到所有數都在一個數組里邊。此時便是完成了合並。如下圖演示:

photo5

photo6

  • 整個過程(包括拆分和合並)如下:

photo7


代碼如下:


#include<iostream>
#include<cstdlib>
#include<vector>
using namespace std;

void Split(vector<int>& pos, vector<int>& temp, const int start, const int end);
void Merge(vector<int>& pos, vector<int>& temp, const int left, const int mid, const int right);
void MergeSort(vector<int>& pos, const int start, const int end);
void Display1(vector<int>& pos);
void Display2(vector<int>& pos);

int main()
{
	int n;
	cout << "請輸入排序的數的個數" << endl;
	cin >> n;
	
	vector<int>pos(n, 0);//申請n個數
	
	cout << "請輸入需要排序的數" << endl;
	for (int i = 0; i < n; i++)
		cin >> pos[i];//初始化數據
	
	Display1(pos);//顯示排序前的數組

	MergeSort(pos, 0, pos.size() - 1);//從第幾個數開始,0個到最后一個數進行歸並排序
	Display2(pos);//顯示排序后的數組
	
	pos.clear();
	return 0;
}

//拆分
void Split(vector<int>& pos, vector<int>& temp, const int start, const int end)
{
	if (start < end)//條件,不能分割為止
	{
		int mid;//中間數定位
		mid = (start + end) / 2;
		Split(pos, temp, start, mid);//左邊拆分
		Split(pos, temp, mid + 1, end);//右邊拆分
		Merge(pos, temp, start, mid, end);//歸並
	}
}

//合並
void Merge(vector<int>& pos, vector<int>& temp, const int left, const int mid, const int right)
{
	int i, j, k;
	i = left;
	j = mid + 1;
	k = 0;
	/*
		i 表示第一個數組,從左到中間的數
		j 表示第二個數組,從中間到右邊的數
		k 表示臨時數組中的下表
	*/
	while (i <= mid && j <= right)//兩個數組判比
	{
		if (pos[i] <= pos[j])//如果左邊的大於右邊的
		{
			temp[k] = pos[i];//左邊的放進臨時數組中
			k++; i++;//繼續跟下一個比較
		}
		else
		{
			temp[k] = pos[j];//如果右邊的大於左邊
			k++; j++;//同樣放入臨時數組中,繼續跟下一個比較
		}
	}
	//當一方數組中有剩余的時候,把他放進臨時數組中,然后等待歸並
	while (i <= mid)
	{
		temp[k] = pos[i];
		k++; i++;
	}
	while (j <= right)
	{
		temp[k] = pos[j];
		k++; j++;
	}
	//把臨時數組中的內容復制到實際數組中
	for (int i = 0; i < k; i++)
		pos[left + i] = temp[i];
}

//排序算法
void MergeSort(vector<int>& pos, const int start, const int end)
{
	vector<int>temp(pos.size(), 0);//創建臨時數組
	Split(pos, temp, start, end);
	temp.clear();
}

void Display1(vector<int>& pos)
{
	cout << "排序前的數組如下" << endl;
	for (int i = 0; i < pos.size(); i++)
	{
		cout << pos[i] << " ";
	}
	cout << endl;
}

void Display2(vector<int>& pos)
{
	cout << "排序后的數組如下" << endl;
	for (int i = 0; i < pos.size(); i++)
	{
		cout << pos[i] << " ";
	}
	cout << endl;
}


程序執行結果圖

photo8


有什么問題或者錯誤可以評論留言,歡迎指正



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM