我正在编写一个函数来获取名为vector<size_t>
和a
的两个已排序b
的交集。该函数迭代两个向量,从a
中删除b
中不存在的任何内容,以便a
中剩余的任何内容都是两者的交集。代码在这里:
void intersect(vector<size_t> &a, vector<size_t> &b) {
vector<size_t>::iterator aItr = a.begin();
vector<size_t>::iterator bItr = b.begin();
vector<size_t>::iterator aEnd = a.end();
vector<size_t>::iterator bEnd = b.end();
while(aItr != aEnd) {
while(*bItr < *aItr) {
bItr++;
if(bItr == bEnd) {
a.erase(aItr, aEnd);
return;
}
}
if (*aItr == *bItr) aItr++;
else aItr = a.erase(aItr, aItr+1);
}
}
我收到了一个很大的错误。我正在踩调试器,一旦它通过第8行“while(*bItr < *aItr)
”b
似乎消失了。调试器似乎不知道b
甚至存在!当b
返回到循环顶部后重新生成时,它现在采用a
的值!
这是我期望在动态内存错误中看到的一种行为,但正如您所看到的,我在这里没有管理任何动态内存。我非常困惑,可以真正使用一些帮助。
提前致谢!
答案 0 :(得分:3)
好吧,也许您应该首先解决代码的一个主要问题:迭代器失效。
请参阅StackOverflow上的Iterator invalidation rules。
当您擦除向量中的元素时,在删除点处进入该向量的迭代器不会保证有效。但是,您的代码假定aEnd有效(感谢@SidS)。
我猜想这就是你所看到的原因,或者也许是你的编译器优化标志可以改变执行流程,不必要的变量的生命周期等等。
另外,作为@KT。注意,你的擦除可能非常昂贵,使你的算法在a。的长度上可能是二次时间。
答案 1 :(得分:1)
您假设b包含至少一个元素。要解决这个问题,您可以在第一次循环之前添加它:
if (bItr == bEnd)
{
a.clear();
return;
}
此外,由于您正在删除a
中的元素,aEnd
将无效。将aEnd
的每次使用替换为a.end()
。
std::set_intersection
可以为您完成所有这些:
void intersect(vector<size_t> &a, const vector<size_t> &b)
{
auto it = set_intersection(a.begin(), a.end(), b.begin(), b.end(), a.begin());
a.erase(it, a.end());
}