map的并集,用相同的键将对应的值相加
Union of map with adding up the corresponding values with the same key
我有两个std::map<char, int> A1, A2;
,我想合并这两个地图。问题是,我如何编写最有效的代码来将两个映射中的相同键的值相加?
A1: ('a', 10), ('c', 8), ('z', 7)
A2: ('c', 12), ('q', 9), ('s', 2), ('u', 8)
A3 = merge(A1, A2); // A3 should be: ('a', 10), ('c', 20), ('q', 9), ('s', 2), ('u', 8), ('z', 7)
更新:我能想到的如下:
std::map<char, int>::iterator it;
for (it = A2.begin(); it != A2.end(); it++)
{
A1[ it->first ] += it->second;
}
有更好的方法吗?
试试下面的
#include <iostream>
#include <map>
int main()
{
std::map<char, int> m1 = { { 'a', 10 }, { 'c', 8 }, { 'z', 7 } },
m2 = { { 'c', 12 }, { 'q', 9 }, { 's', 2 }, { 'u', 9 } };
for ( const auto &p : m2 ) m1[p.first] += p.second;
for ( const auto &p : m1 ) std::cout << p.first << 't' << p.second << std::endl;
return 0;
}
好吧。因为您使用的是std::map
,所以遍历集合的顺序定义得很好(参见遍历std::map的顺序是否已知(并由标准保证)?)
这意味着您可以对输入映射进行相当简单的一次遍历迭代,而不必在其中任何一个中进行一次查找。我相信,推进一个普通的前向迭代器应该是0(1)步。
插入是有趣的…根据cppreference,可以给std::map::insert
提供一个提示参数,使得插入
如果插入发生在提示之前的位置,则为平摊常数,否则为容器大小的对数。
现在,假设我没有完全糊涂,当我们按顺序插入元素时,我们总是在映射的最后插入。因此,提示总是a3.end()
。在c++ 11之前,您可以保留最后一个insert
操作的返回结果,该结果将是紧接在结束之前的元素,因此紧接在下一个要插入的元素之前,并将其用作提示。
快速示例代码,可能工作,也可能不工作,E&OE, YMMV等!
std::map<char, int> a1, a2, a3;
// populate a1 and a2 yourself here. elided for brevity.
auto a1i = a1.begin();
auto a2i = a2.begin();
while(a1i != a1.end() && a2i != a2.end())
{
if (a1i->first < a2i->first)
{
a3.insert(a3.end(), *a1i);
a1i++;
}
else if (a1i->first == a2i->first)
{
a3.insert(
a3.end(),
std::make_pair(a1i->first, a1i->second + a2i->second));
a1i++;
a2i++;
}
else if (a1i->first > a2i->first)
{
a3.insert(a3.end(), *a2i);
a2i++;
}
continue;
}
// push remaining elements, if any, into a3.
// this is O(NlogN), but you should use hinted insert as above to make it O(N)
a3.insert(a1i, a1.end());
a3.insert(a2i, a2.end());
注意:与您的示例代码相比,这种方式避免了每次迭代的树查找,并且可以将不可变映射用作输入。与您的代码的O(NlogN)相比,我的代码的最佳性能应该是O(N)(平摊,假设我正确使用了insert
提示)。为了简洁起见,上面最后的insert
代码以效率较低的形式保留。
现在,还有一个可能的内存分配问题。如果其中一个(或两个)源映射非常大,那么最好能预先分配一块内存,至少适合两个映射中较大的一个。但是,std::map
没有reserve
方法。如果您要使用一个合适的分配器,它支持为您的新map实例预分配内存池,那么您可能会从系统中挤出更多的性能。
最终,除非您提供一些效率度量,否则任何答案的有用程度都是有限的;-)
- 没有找到相关文章