C++ STL merge/inplace_merge 歸併函數簡單使用

C++ STL merge/inplace_merge 歸併函數簡單使用

c++自帶的歸併函數也是比較好用的,可以節省很多時間,歸併也分爲異地歸併和原地歸併,先來看一下異地歸併

異地歸併

異地歸併需要一個額外的空間來存儲歸併後的結果,通常是通過傳遞該空間的起始迭代器(最底層迭代器)來實現的

/*
function      : 將兩個有序序列按照運算符歸併爲一個有序序列
param beign1  : 子序列1起始迭代器
param end1    : 子序列1結束迭代器
param beign2  : 子序列2起始迭代器
param end2    : 子序列2結束迭代器
param both    : 結果序列起始迭代器
param compare : 比較運算符,默認是小於,也就是升序歸併
*/
merge(begin1, end1, begin2, end2, both, compare);

示例1.1

在這裏插入圖片描述

vector<int> seq1 = {1,3,5,7};
vector<int> seq2 = {2,4,6,8};
vector<int> merge_seq(8);

merge(seq1.begin(), seq1.end(), seq2.begin(), seq2.end(), merge_seq.begin());

for(int i=0; i<merge_seq.size(); i++) 
	cout<<merge_seq[i]<<" ";
cout<<endl;

示例1.2

還可以通過修改比較運算符達到預期的效果
比如:以到原點的距離爲大小比較
在這裏插入圖片描述

#define dist(x) ((int)fabs(x))
struct cmp
{
	bool operator() (int a, int b){return dist(a) < dist(b);}
};

vector<int> seq1 = {1,3,5,7};
vector<int> seq2 = {1,-3,-5,-7};
vector<int> merge_seq(8);

merge(seq1.begin(), seq1.end(), seq2.begin(), seq2.end(), merge_seq.begin(), cmp());

for(int i=0; i<merge_seq.size(); i++) 
	cout<<merge_seq[i]<<" ";
cout<<endl;

原地歸併

原地歸併不需要額外的空間,只需要指定分界點即可

/*
function      : 將一個兩部分有序的數組歸併到一個數組
param l_begin : 左子數組起始迭代器(也是整個數組的起始迭代器 
param r_begin : 右子數組起始迭代器
param end     : 整個數組結束迭代器
param compare : 比較運算符,默認是小於,也就是升序歸併
*/
inplace_merge(l_begin, r_begin, end, compare); 

注意:
在STL中區間習慣是左閉右開,也就是說,假設兩個有序的子序列下標是[0,3][4,7],那麼分界點應該是4,即兩個子區間應該是[0,4)[4,8)兩個區間,傳遞參數的時候需要注意

如果記不住,可以這樣傳參:(起始迭代器,右半部分序列起始迭代器,結束迭代器)

示例 2.1

在這裏插入圖片描述

vector<int> seq = {1,3,5,7,2,4,6,8,9};
	
inplace_merge(seq.begin(), seq.begin()+4, seq.end());

for(int i=0; i<seq.size(); i++) 
	cout<<seq[i]<<" ";
cout<<endl;

示例2.2

同樣可以通過自定義的比較函數來實現奇怪的功能,以【到原點距離】作爲比較判據
在這裏插入圖片描述

#define dist(x) ((int)fabs(x))
struct cmp
{
	bool operator() (int a, int b){return dist(a) < dist(b);}
};

vector<int> seq = {1,3,5,7,-1,-3,-5,-7,-9};

inplace_merge(seq.begin(), seq.begin()+4, seq.end(), cmp());

for(int i=0; i<seq.size(); i++) 
	cout<<seq[i]<<" ";
cout<<endl;

附:原地歸併實現歸併排序(遞歸)

在這裏插入圖片描述
遞歸邊界條件是數組長度爲1,就不操作

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

void merge_sort(vector<int>& nums, int l, int r)
{
	if(l<r)
	{
		int mid = (l+r)/2;
		merge_sort(nums, l, mid);
		merge_sort(nums, mid+1, r);
		inplace_merge(nums.begin()+l, nums.begin()+mid+1, nums.begin()+r+1);	
	}
}

int main()
{
	vector<int> nums{3,1,4,2,7,5,6,8,9};
	
	merge_sort(nums, 0, nums.size()-1);
	
	for(int i=0; i<nums.size(); i++) 
		cout<<nums[i]<<" ";
	cout<<endl;
	
	return 0;
}

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