您可以编写一个算法来合并它们,方法是按顺序按顺序遍历两个序列,并在适当的位置插入。
我选择一个(貌似更贴切)数据结构在这里:std::map<Value, Occurence>
:
#include <map>
using namespace std;
using Value = int;
using Occurence = unsigned;
using Histo = map<Value, Occurence>;
如果你坚持连续的存储,boost::flat_map<>
这里应该是你的朋友(和简易替换)。
算法(与你的输入测试,阅读说明注释):
void MergeInto(Histo& target, Histo const& other)
{
auto left_it = begin(target), left_end = end(target);
auto right_it = begin(other), right_end = end(other);
auto const& cmp = target.value_comp();
while (right_it != right_end)
{
if ((left_it == left_end) || cmp(*right_it, *left_it))
{
// insert at left_it
target.insert(left_it, *right_it);
++right_it; // and carry on
} else if (cmp(*left_it, *right_it))
{
++left_it; // keep left_it first, so increment it
} else
{
// keys match!
left_it->second += right_it->second;
++left_it;
++right_it;
}
}
}
这真的很直截了当!
测试程序:看到它Live On Coliru
#include <iostream>
// for debug output
static inline std::ostream& operator<<(std::ostream& os, Histo::value_type const& v) { return os << "{" << v.first << "," << v.second << "}"; }
static inline std::ostream& operator<<(std::ostream& os, Histo const& v) { for (auto& el : v) os << el << " "; return os; }
//
int main(int argc, char *argv[])
{
Histo A { { 8, 1 }, { 5, 1 } };
Histo B { { 2, 1 }, { 8, 1 } };
std::cout << "A: " << A << "\n";
std::cout << "B: " << B << "\n";
MergeInto(A, B);
std::cout << "merged: " << A << "\n";
}
印刷:
A: {5,1} {8,1}
B: {2,1} {8,1}
merged: {2,1} {5,1} {8,2}
你可以洗牌接口的情况下,一点点你真的想要合并到一个新的对象(C
):
// convenience
Histo Merge(Histo const& left, Histo const& right)
{
auto copy(left);
MergeInto(copy, right);
return copy;
}
现在你可以只写
Histo A { { 8, 1 }, { 5, 1 } };
Histo B { { 2, 1 }, { 8, 1 } };
auto C = Merge(A, B);
请参阅Live on Coliru, too
您确定这是预期的产出吗?有两次出现'8',每次出现2次? –
这就是我想要做的。最初,我想收缩数组并在合并两个数组后增加元素的数量,但是我认为这可能会超过我的限制O(nlogn)。所以我会有C [] [] = [[2,1],[8,2],[5,1]] – Masterminder
那么你需要打包还是打包哪个输出?该算法可以显着不同。 –