C++ 如何合并两个已排序的向量并合并重叠的元素?

C++ 如何合并两个已排序的向量并合并重叠的元素?,c++,boost,c++11,vector,set,C++,Boost,C++11,Vector,Set,让 我对使用标准库(或类似于Boost的东西)是否可以实现这一点感兴趣。手动执行此操作的代码并不特别复杂,但我不想重新发明轮子 我能找到的唯一其他相关操作是。它也不会合并元素,并且会涉及另一个组合过程。我认为std::merge与boost::function\u output\u iterator的使用非常干净 C[k].first = A[i].first; // == B[j].first. set_union does this C[k].second = A[i].second +

我对使用标准库(或类似于Boost的东西)是否可以实现这一点感兴趣。手动执行此操作的代码并不特别复杂,但我不想重新发明轮子


我能找到的唯一其他相关操作是。它也不会合并元素,并且会涉及另一个组合过程。

我认为
std::merge
boost::function\u output\u iterator
的使用非常干净

C[k].first = A[i].first; // == B[j].first.  set_union does this
C[k].second = A[i].second + B[j].second; // set_union does NOT do this.

注意。使用的建议是。

这里有一个独立的通用算法
merge\u elements
的实现:

1 3.6
2 3
3 5.5
4 2.2
5 3.4
#包括
#包括
模板
输出合并元素(LInput lbegin、LInput lend、,
林普特·贝金,林普特·伦德,
输出(输出){
while(true){
如果(lbegin==lend){
返回标准::复制(rbegin、rend、out);
}
如果(rbegin==rend){
返回std::复制(lbegin、lend、out);
}
if(lbegin->firstfirst){
*out++=*lbegin++;
}否则如果(rbegin->firstfirst){
*out++=*rbegin++;
}否则{
*out++=std::make_pair(lbegin->first,lbegin->second+rbegin->second);
++勒贝金;
++贝金;
}
}
}
#包括
#包括
#包括
/*元素的便利类型别名*/
使用Elem=std::pair;
/*元素容器的便利类型别名*/
使用Elems=std::vector;
int main(){
//样本数据。
元素lhs{{1,2.3},{2,3},{5,3.4};
元素rhs{{1,1.3}、{3,5.5}、{4,2.2};
元素结果;
//合并并使用appender追加元素。
合并元素(std::begin(lhs),
标准::结束(左侧),
标准::开始(rhs),
标准::结束(rhs),
标准:背向插入器(结果);
//打印结果。
用于(常量自动和元素:结果){

std::cout
std::merge
可以用一个非常聪明的输出迭代器来完成,但我认为一个新的算法是better@MooingDuck您是否在考虑类似于
back\u inserter
的东西,但它会检查新元素是否与前一个相同?我不同意……这里的目标是错误的,任何“聪明的”标准算法和花哨迭代器的应用程序编写起来会比较慢,就像Alex的回答风格中明显的循环方法一样冗长和复杂。@Praetorian:如果你制作一个迭代器,其中包含对容器的引用,它可以查看容器的最后一个元素,并将其与o进行比较ne被传递,然后决定是将新元素推到容器的末尾,还是将其与前一个元素组合。好吧-我不知道boost::function\u output\u iterator是否很好地解决了这个问题……我同意这是一个很好的解决方案,boost就在表上。(如果没有这一点,就不值得大惊小怪地编写一个迭代器来返回一个代理来捕获赋值。)
C[k].first = A[i].first; // == B[j].first.  set_union does this
C[k].second = A[i].second + B[j].second; // set_union does NOT do this.
#include <algorithm>
#include <iostream>
#include <vector>

#include <boost/function_output_iterator.hpp>

/* Convenience type alias for our element. */
using Elem = std::pair<int, double>;

/* Convenience type alias for the container of our elements. */
using Elems = std::vector<Elem>;

/* Our appender that will be created with boost::function_output_iterator. */
class Appender {
  public:

  /* Cache the reference to our container. */
  Appender(Elems &elems) : elems_(elems) {}

  /* Conditionally modify or append elements. */
  void operator()(const Elem &elem) const {
    if (!elems_.empty() && elems_.back().first == elem.first) {
      elems_.back().second += elem.second;
      return;
    }  // if
    elems_.push_back(elem);
  }

  private:

  /* Reference to our container. */      
  Elems &elems_;

};  // Appender

int main() {
  // Sample data.
  Elems lhs {{1, 2.3}, {2, 3}, {5, 3.4}};
  Elems rhs {{1, 1.3}, {3, 5.5}, {4, 2.2}};
  Elems result;
  // Merge and use appender to append elements.
  std::merge(std::begin(lhs),
             std::end(lhs),
             std::begin(rhs),
             std::end(rhs),
             boost::make_function_output_iterator(Appender(result)));
  // Print result.
  for (const auto &elem : result) {
    std::cout << elem.first << ' ' << elem.second << std::endl;
  }  // for
}
1 3.6
2 3
3 5.5
4 2.2
5 3.4
#include <algorithm>
#include <utility>

template <typename LInput, typename RInput, typename Output>
Output merge_elements(LInput lbegin, LInput lend,
                      RInput rbegin, RInput rend,
                      Output out) {
    while(true) {
        if (lbegin == lend) {
            return std::copy(rbegin, rend, out);
        }

        if (rbegin == rend) {
            return std::copy(lbegin, lend, out);
        }

        if (lbegin->first < rbegin->first) {
            *out++ = *lbegin++;
        } else if (rbegin->first < lbegin->first) {
            *out++ = *rbegin++;
        } else {
            *out++ = std::make_pair(lbegin->first, lbegin->second + rbegin->second);
            ++lbegin;
            ++rbegin;
        }
    }
}

#include <iostream>
#include <iterator>
#include <vector>

/* Convenience type alias for our element. */
using Elem = std::pair<int, double>;

/* Convenience type alias for the container of our elements. */
using Elems = std::vector<Elem>;

int main() {
  // Sample data.
  Elems lhs {{1, 2.3}, {2, 3}, {5, 3.4}};
  Elems rhs {{1, 1.3}, {3, 5.5}, {4, 2.2}};
  Elems result;
  // Merge and use appender to append elements.
  merge_elements(std::begin(lhs),
                 std::end(lhs),
                 std::begin(rhs),
                 std::end(rhs),
                 std::back_inserter(result));
  // Print result.
  for (const auto &elem : result) {
    std::cout << elem.first << ' ' << elem.second << std::endl;
  }  // for
}
#include <iostream>
#include <iterator>
#include <map>

/* Convenience type alias for the container of our elements. */
using Elems = std::map<int, double>;

int main() {
  // Sample data.
  Elems lhs {{1, 2.3}, {2, 3}, {5, 3.4}};
  Elems rhs {{1, 1.3}, {3, 5.5}, {4, 2.2}};
  Elems result;
  // Merge and use appender to append elements.
  merge_elements(std::begin(lhs),
                 std::end(lhs),
                 std::begin(rhs),
                 std::end(rhs),
                 std::inserter(result, result.begin()));
  // Print result.
  for (const auto &elem : result) {
    std::cout << elem.first << ' ' << elem.second << std::endl;
  }  // for
}