我已经编写了一个代码来解决以下问题:我们有map<double,double>
个(相对)大量的项目。我们想合并相邻的项目,以减少地图的大小,保持一定的“损失因子”尽可能低。
为此,我首先填充一个包含相邻迭代器和相关损耗因子的列表(假设每个列表元素具有以下类型:
struct myPair {
map<double,double>::iterator curr, next;
double loss;
myPair(map<double,double>::iterator c, map<double,double>::iterator n,
double l): curr(c), next(n), loss(l) {}
};
)。这样做如下:
for (map<double,double>::iterator it1 = myMap.begin(); it1 != --(myMap.end());
it1++) {
map<double,double>::iterator it2 = it1; it2++;
double l = computeLoss(it1,it2);
List.push(myPair(it1,it2,l));
}
然后,我找到对应于最低损失因子的列表元素,erase
来自map
和insert
的相应元素一个新元素(合并curr
的结果和next
中的map
}。由于这也会更改next
之后或curr
之后的元素对应的列表元素,因此我会更新相应的条目以及相关的损失因子。
(我没有深入了解如何有效地实现上述内容,但基本上我将双链表与堆结合起来。)
虽然erase
操作不应该使程序的某些特定输入实例的剩余迭代器无效,但是在我尝试从{{1}擦除元素时,我得到了double free or corruption
错误。 }}
我尝试跟踪此情况,当两个地图元素的map
和first
条目非常接近时(更准确地说second
的{{1}}时,似乎会发生这种情况。 }}和first
非常接近)。
奇怪的是,我在填充列表的同时放置curr
以确保所有条目next
和assert
在循环中不同且curr
删除元素。第二个失败了!
如果有人能帮助我,我将不胜感激。
P.S。对不起,我很抱歉,但我希望尽可能保持细节。
更新:这是我从地图中删除元素的(非常简化的版本):
next
答案 0 :(得分:0)
容器修改后myPair
中存储的迭代器保持无效。你应该避免这种技术。可能当您查看头文件时,您会找到一些适合您的任务的草稿?
答案 1 :(得分:0)
正如其他人已经提到的,事实证明使用double
作为map
的关键是有问题的。特别是在计算值时。
因此,我的解决方案是使用std::multimap
而不是map
(然后在填充地图后将元素与相同的键合并)。有了这个,例如即使a
非常接近t.curr
和t.next
或任何其他元素的键,确保insert
操作创建一个新的元素, iterator
中的现有list
不会指向该内容。