STL----已序类排序---merge方法

前言:

merge类算法的前提依然是区间是有序的,主要是用来合并两个容器的元素或者是单个容器两段区间的元素,一说到这里,我们就会想起归并排序,对,我们也可以用这个算法来简化我们的代码量,具体看后面的例子。

merge

//default (1)	
template <class InputIterator1, class InputIterator2, class OutputIterator>
  OutputIterator merge (InputIterator1 first1, InputIterator1 last1,
                        InputIterator2 first2, InputIterator2 last2,
                        OutputIterator result);

//custom (2)	
template <class InputIterator1, class InputIterator2,
          class OutputIterator, class Compare>
  OutputIterator merge (InputIterator1 first1, InputIterator1 last1,
                        InputIterator2 first2, InputIterator2 last2,
                        OutputIterator result, Compare comp);

merge函数的作用是:将两个有序的序列合并为一个有序的序列。函数参数:merge(first1,last1,first2,last2,result,compare);

firs1t为第一个容器的首迭代器,last1为第一个容器的末迭代器,first2为第二个容器的首迭代器,last2为容器的末迭代器,result为存放结果的容器,comapre为比较函数(可略写,默认为合并为一个升序序列)。
还有就是前面两对迭代器可以指向同一个容器的不同段,但是后面那个就不允许指向前面的容器。

源码

template <class InputIterator1, class InputIterator2, class OutputIterator>
  OutputIterator merge (InputIterator1 first1, InputIterator1 last1,
                        InputIterator2 first2, InputIterator2 last2,
                        OutputIterator result)
{
  while (true) {
    if (first1==last1) return std::copy(first2,last2,result);
    if (first2==last2) return std::copy(first1,last1,result);
    *result++ = (*first2<*first1)? *first2++ : *first1++;
  }
}

举个例子:

// merge algorithm example
#include <iostream>     // std::cout
#include <algorithm>    // std::merge, std::sort
#include <vector>       // std::vector

int main () {
  int first[] = {5,10,15,20,25};
  int second[] = {50,40,30,20,10};
  std::vector<int> v(10);

  std::sort (first,first+5);
  std::sort (second,second+5);
  std::merge (first,first+5,second,second+5,v.begin());

  std::cout << "The resulting vector contains:";
  for (std::vector<int>::iterator it=v.begin(); it!=v.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';

  return 0;
}

在这里插入图片描述

inplace_merge

这个的话,跟前面用法没什么两样,就是一个容器内分两个有序的部分归并到本身的容器,唯一区别就是参数不一样

其次:inplace_merge在额外内存足够的情况下,恰好做 N - 1 次对比(N其实就是两段有序列长度之和 ),否则(没有足够内存用来缓存)复杂度就是 N*log(N),即若尝试分配缓存失败就会用比较低效的算法来执行.

实际上它也是需要申请空间来做的,但申请失败就是低效的排序算法来用。

//default (1)	
template <class BidirectionalIterator>
  void inplace_merge (BidirectionalIterator first, BidirectionalIterator middle,
                      BidirectionalIterator last);

//custom (2)	
template <class BidirectionalIterator, class Compare>
  void inplace_merge (BidirectionalIterator first, BidirectionalIterator middle,
                      BidirectionalIterator last, Compare comp);

举个例子:

// inplace_merge example
#include <iostream>     // std::cout
#include <algorithm>    // std::inplace_merge, std::sort, std::copy
#include <vector>       // std::vector

int main () {
  int first[] = {5,10,15,20,25};
  int second[] = {50,40,30,20,10};
  std::vector<int> v(10);
  std::vector<int>::iterator it;

  std::sort (first,first+5);
  std::sort (second,second+5);

  it=std::copy (first, first+5, v.begin());
     std::copy (second,second+5,it);

  std::inplace_merge (v.begin(),v.begin()+5,v.end());

  std::cout << "The resulting vector contains:";
  for (it=v.begin(); it!=v.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';

  return 0;
}

在这里插入图片描述

总结:

假设M,N分别为两段有序列的长度.
merge时间复杂度为O(min(M,N)),空间复杂度O(M+N).
inplace_merge,在分配缓存成功时,时间复杂度O(M+N),空间复杂度看分配的缓存,即可能为O(M),O(N)或O(M+N),否则,时间复杂度为O(N*log(N)),空间复杂度为O(1).

归并排序实例

给定你一个长度为n的整数数列。
请你使用归并排序对这个数列按照从小到大进行排序。
并将排好序的数列按顺序输出。
输入格式
输入共两行,第一行包含整数 n。
第二行包含 n 个整数(所有整数均在1~109范围内),表示整个数列。
输出格式
输出共一行,包含 n 个整数,表示排好序的数列。

数据范围
1≤n≤100000
输入样例:
5
3 1 2 4 5
输出样例:
1 2 3 4 5

思路:没啥说的,模板题

没用STL的做法
# include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int n;
int a[N],q[N];
void merge(int left,int right)
{
   if(left>=right) return;
   int mid = (left+right)>>1;
   merge(left,mid);
   merge(mid+1,right);
   //合并两段数据
   int i=left,j = mid+1;
   int k = 0;
   while(i<=mid && j<=right){
       if(a[i]<=a[j]){
           q[k++] = a[i];
           ++i;
       }
       else{
           q[k++] = a[j];
           ++j;
       }
   }
   while(i<=mid){
       q[k++] = a[i++];
   }
   while(j<=right){
       q[k++] = a[j++];
   }
   for(int i=0;left<=right;++left){
       a[left] = q[i++];
   }
   return ;
}
int main(void)
{
    cin>>n;
    for(int i=1;i<=n;++i){
        cin>>a[i];
    }
    merge(1,n);
    for(int i=1;i<=n;++i){
        cout<<a[i]<<' ';
    }
    return 0 ;
}
用inplace_merge算法
# include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int n;
int a[N],q[N];
void merge(int left,int right)
{
   if(left>=right) return;
   int mid = (left+right)>>1;
   merge(left,mid);
   merge(mid+1,right);
   //合并两段数据
   inplace_merge(begin(a)+left,begin(a)+mid+1,begin(a)+right+1);
   //因为这里范围是    [begin,middle)    ,    [middle,end)
   return ;
}
int main(void)
{
    cin>>n;
    for(int i=1;i<=n;++i){
        cin>>a[i];
    }
    merge(1,n);
    for(int i=1;i<=n;++i){
        cout<<a[i]<<' ';
    }
    return 0 ;
}
inplace_merge源码剖析
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STL中的merge()函数是用来将两个有列合并为一个有列的。它可以接受多种参数形式,但最常用的形式是merge(first1, last1, first2, last2, result, compare),其中first1和last1指定了第一个有列的范围,first2和last2指定了第二个有列的范围,result指定了合并后的有列的存储位置,compare是一个可选的比较函数,用于指定元素的比较规则。如果不提供compare函数,merge()将会按默认的升规则进行排序。 在给定的代码示例中,使用了自定义的排序规则cmp来对结构体A进行排序。首先将两个有列a和b按照规则cmp进行合并,并将结果存储到列c中。最后通过遍历列c来打印合并后的结果。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [stl算法之merge](https://blog.csdn.net/FairLikeSnow/article/details/114042023)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [stl merge函数使用](https://blog.csdn.net/m0_37579232/article/details/89785635)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值