我正在尝试删除struct的向量中的重复,这个重复由结构中的qieid
确定:
struct infotable
{
int qieid;
int fid;
int valid;
};
我写了一个子功能来执行此操作:
void erase_duplicate(vector<infotable> &info)
{
vector<infotable>::iterator it0,it1;
for(it0 = info.begin();it0 != info.end()-1; it0++)
{
//it1 = find(qieidarray1.begin(),it0,*it0);
for(it1 = it0 +1;it1 != info.end(); it1++)
{
if((*it1).qieid == (*it0).qieid)
it1 = info.erase(it1);
}
}
}
但是我对这段代码有些问题。 当向量中的结构数量很小时,它可以正常工作。但是当我在向量中有超过3000个结构时,程序将出错并且我有:
分段错误11
显示在我的屏幕上。 我知道这是一个内存访问问题,我可能会访问我不应该触摸的地方,因为我在向量中有这么多元素。 但是,无论如何我可以改进我的代码以获得更好的性能(运行更多元素)?
答案 0 :(得分:4)
使用erase时,它将使迭代器无效。
for(it1 = it0 +1;it1 != info.end(); )
{
if((*it1).qieid == (*it0).qieid)
it1 = info.erase(it1);
else
it1++;
}
答案 1 :(得分:4)
您还可以使用<algorithm>
函数来执行此操作,尤其是std::unique
。
首先,按qieid
排序,然后使用unique
,它会在末尾移动“已删除”元素并返回一个新的迭代器,然后您可以使用它来实际删除这些元素。
std::sort(info.begin(), info.end(), [](const infotable& a, const infotable& b) {
return a.qieid < b.qieid;
});
auto newIt = std::unique(info.begin(), info.end(), [](const infotable& a, const infotable& b) {
return a.qieid == b.qieid;
});
info.erase(newIt, info.end());
这将在O(n + log n)中运行,而您的原始解决方案具有O(n 2 )时间复杂度。就个人而言,我更喜欢这个解决方案,特别是因为它更具表现力,所以更容易看到代码在做什么。
注意:如果您的编译器已经支持C ++ 14的通用lambdas,则可以使用以下命令简化表达式:[](const auto& a, const auto& b) { ... }
答案 2 :(得分:2)
您可以使用std::set
技巧删除重复项,
它非常易读,易于维护,但效率较低。
std::vector<int> r = {14,26,58,56,26,14};
std::set<int> s(r.begin(),r.end());
r = std::vector<int>(s.begin(),s.end());
你需要给std :: set你自己的比较函数,以便它能与你的结构一起使用。