歸並排序
這次我們來講述歸並排序的基本思想。
- 歸並排序,首先把一個數組中的元素,按照某一方法,先拆分了之后,按照一定的順序各自排列,然后再歸並到一起,使得歸並后依然是有一定順序的 。
- 歸並排序算法可以利用遞歸的思想或者迭代的思想去實現。首先我們先把一個無序的數組去拆分,然后利用一定的規則,去合並。類似於二叉樹的結構。其總的時間復雜度為O( n log n)。空間復雜度為 S(nlogn)
示例圖如下:
- 首先我們看到,一個無序的數組如下,為了簡約,以及簡便解釋,我們定義了8個元素。
- 然后,我們把該8個元素進行划分,分成左邊四個,和右邊四個,如下圖。
- 依次按照上邊的方法,把剩余的數組繼續拆分,一直拆到只剩下一個元素的時候,停止。如下圖
- 由於存在8個單獨的子元素,然后我們兩兩把元素合並,並且按照一定順序排序(此處用從小到大的順序排序)。如下圖:
- 此時,我們可以看到我們又得到了四個不同顏色的數組,並且在這個數組里邊,也是按照一定的順序排好序的。隨后,繼續利用這種方法,把剩余的繼續合並,一直合並到所有數都在一個數組里邊。此時便是完成了合並。如下圖演示:
- 整個過程(包括拆分和合並)如下:
代碼如下:
#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;
}
程序執行結果圖
有什么問題或者錯誤可以評論留言,歡迎指正