【发布时间】:2013-09-12 23:17:34
【问题描述】:
我编写了一个代码来解决以下问题:我们有一个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));
}
然后,我从map和insert中找到与最低损失因子对应的列表元素erase,在@中找到一个新元素(合并curr和next的结果) 987654329@。由于这也会更改与next 之后或curr 之前的元素对应的列表元素,因此我更新了相应的条目以及相关的损失因子。
(我没有详细介绍如何有效地实现上述内容,但基本上我将双链表和堆结合起来)。
虽然erase 操作不应使程序的某些特定输入实例的剩余迭代器无效,但我在尝试从map 中删除元素时得到了double free or corruption 错误。
我试图跟踪这一点,似乎当两个地图元素的first 和second 条目非常接近时(更准确地说,当curr 和next 的firsts 非常接近时,就会发生这种情况关闭)。
奇怪的是,我在填充列表时放置了一个assert,以确保在删除元素的循环中所有条目中的curr 和next 是不同的和相同的assert。第二个失败了!
如果有人可以帮助我,我将不胜感激。
附:很抱歉我说的不是很精确,但我想尽量减少细节。
更新:这是(一个非常简化的版本)我如何从地图中删除元素:
while (myMap.size() > MAX_SIZE) {
t = list.getMin();
/* compute the merged version ... let's call the result as (a,b) */
myMap.erase(t.curr);
myMap.erase(t.next);
myMap.insert(pair<double,double>(a,b));
/* update the adjacent entries */
}
【问题讨论】:
-
请显示删除元素的代码。
-
我现在就添加代码。
-
顺便说一下,在所示示例中,
a >= t.curr->first和a <= t.next->first,因此新元素将被替换在与两个已删除元素相同的位置。 -
看起来你想要类似于堆或树的东西而不是列表,这样你就不必搜索最小的损失因子。在这种情况下,更新成本 ln(N)。
-
旁注:使用
double作为映射键可能会产生相当令人惊讶的结果。如果您通过计算获得键值,您可能会在期望不精确的地方获得不同的键,这仅仅是由于精度错误。
标签: c++ dictionary iterator std stdmap