您可以編寫一個算法來合併它們,方法是按順序按順序遍歷兩個序列,並在適當的位置插入。
我選擇一個(貌似更貼切)數據結構在這裏: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
那麼你需要打包還是打包哪個輸出?該算法可以顯着不同。 –