如何在二维容器vector中删除重复元素。
我有一个二维容器,其中有很多重复的数据,请问应该怎么删除。我自己写的代码编译可以通过,但是运行的时候总包错(verctoriteratornotdereferencabl...
我有一个二维容器,其中有很多重复的数据,请问应该怎么删除。我自己写的代码编译可以通过,但是运行的时候总包错(verctor iterator not dereferencable)。
vector<vector<double> > ver;
ver.resize(0,vector<double>(3)); //3个double数值一一对应判断是否相等,若全部相等则删除
vector<double>::iterator iter1_0,iter1_1,iter1_2,iter2_1,iter2_2;
for ( iter1 ; iter1 != ver.end(); iter1 ++)
{
iter1_0 = (*iter1).begin();
iter1_1 = iter1_0 + 1;
iter1_2 = iter1_0 + 2;
for ( iter2 = iter1 + 1; iter2 != ver.end();)
{
iter2_0 = (*iter2).begin();
iter2_1 = iter2_0 + 1;
iter2_2 = iter2_0 + 2;
if ( *iter1_0 == *iter2_0 )
{
if ( *iter1_1 == *iter2_1 )
{
if ( *iter1_2 == *iter2_2 )
{
ver.erase(iter2);
}
else
{
iter2++;
}
}
else
{
iter2++;
}
}
else
{
iter2++;
};
}
} 展开
vector<vector<double> > ver;
ver.resize(0,vector<double>(3)); //3个double数值一一对应判断是否相等,若全部相等则删除
vector<double>::iterator iter1_0,iter1_1,iter1_2,iter2_1,iter2_2;
for ( iter1 ; iter1 != ver.end(); iter1 ++)
{
iter1_0 = (*iter1).begin();
iter1_1 = iter1_0 + 1;
iter1_2 = iter1_0 + 2;
for ( iter2 = iter1 + 1; iter2 != ver.end();)
{
iter2_0 = (*iter2).begin();
iter2_1 = iter2_0 + 1;
iter2_2 = iter2_0 + 2;
if ( *iter1_0 == *iter2_0 )
{
if ( *iter1_1 == *iter2_1 )
{
if ( *iter1_2 == *iter2_2 )
{
ver.erase(iter2);
}
else
{
iter2++;
}
}
else
{
iter2++;
}
}
else
{
iter2++;
};
}
} 展开
4个回答
推荐于2016-03-04 · 知道合伙人互联网行家
关注
展开全部
删除vector中的重复元素,
从容器中元素顺序上可分为2种情形:
1)保持剩余元素顺序不变,特称为稳定删除,对应下面的stable_unique版本函数模板
2)不考虑顺序变化,特称为快速删除。
对应下面的quick_unique版本函数模板。从重复的概念定义也可分为2种情况:
1)基于简单的相等判断
2)基于谓词的等价判断。因此,由排列组合得知应该有4种版本的实现,下面给出代码描述:
//函数对象模板类
2template<typename T>
3struct Predicate
4{
5 Predicate()
6 {
7 }
8
9 Predicate(const T& t)
10 :_t(t)
11 {
12 }
13 bool operator()(const T& t) const
14 {
15 //可以自定义比较实现
16 return _t == t;
17 }
18 //支持std::unique谓词版本的删除
19 bool operator()(const T& l,const T& r) const
20 {
21 //可以自定义比较实现
22 return l == r;
23 }
24 T _t;
25};
26
27//quick_unique版本1: 相等判断
28template<typename T>
29void quick_unique(std::vector<T>& con)
30{
31 std::sort(con.begin(),con.end());
32 con.erase(std::unique(con.begin(),con.end()),con.end());
33}
34
35//quick_unique版本2: 谓词判断
36template<typename T,template <typename U> class Predicate>
37void quick_unique(std::vector<T>& con)
38{
39 std::sort(con.begin(),con.end());
40 con.erase(std::unique(con.begin(),con.end(),Predicate<T>()),con.end());
41}
42
43//stable_unique版本1: 相等判断
44template<typename T>
45void stable_unique(std::vector<T>& con)
46{
47 std::vector<T>::iterator it,ret,beg = con.begin();
48 for (it = ++con.begin();it!=con.end();)
49 {
50 ret = find(beg,it,*it);
51 if (ret != it)
52 it = con.erase(it);
53 else
54 ++it;
55 }
56}
57
58//stable_unique版本2: 谓词判断
59template<typename T,template <typename U> class Predicate>
60void stable_unique(std::vector<T>& con)
61{
62 std::vector<T>::iterator it,ret,beg = con.begin();
63 for (it = ++con.begin();it!=con.end();)
64 {
65 ret = find_if(beg,it,Predicate<T>(*it));
66 if (ret != it)
67 it = con.erase(it);
68 else
69 ++it;
70 }
71}
从容器中元素顺序上可分为2种情形:
1)保持剩余元素顺序不变,特称为稳定删除,对应下面的stable_unique版本函数模板
2)不考虑顺序变化,特称为快速删除。
对应下面的quick_unique版本函数模板。从重复的概念定义也可分为2种情况:
1)基于简单的相等判断
2)基于谓词的等价判断。因此,由排列组合得知应该有4种版本的实现,下面给出代码描述:
//函数对象模板类
2template<typename T>
3struct Predicate
4{
5 Predicate()
6 {
7 }
8
9 Predicate(const T& t)
10 :_t(t)
11 {
12 }
13 bool operator()(const T& t) const
14 {
15 //可以自定义比较实现
16 return _t == t;
17 }
18 //支持std::unique谓词版本的删除
19 bool operator()(const T& l,const T& r) const
20 {
21 //可以自定义比较实现
22 return l == r;
23 }
24 T _t;
25};
26
27//quick_unique版本1: 相等判断
28template<typename T>
29void quick_unique(std::vector<T>& con)
30{
31 std::sort(con.begin(),con.end());
32 con.erase(std::unique(con.begin(),con.end()),con.end());
33}
34
35//quick_unique版本2: 谓词判断
36template<typename T,template <typename U> class Predicate>
37void quick_unique(std::vector<T>& con)
38{
39 std::sort(con.begin(),con.end());
40 con.erase(std::unique(con.begin(),con.end(),Predicate<T>()),con.end());
41}
42
43//stable_unique版本1: 相等判断
44template<typename T>
45void stable_unique(std::vector<T>& con)
46{
47 std::vector<T>::iterator it,ret,beg = con.begin();
48 for (it = ++con.begin();it!=con.end();)
49 {
50 ret = find(beg,it,*it);
51 if (ret != it)
52 it = con.erase(it);
53 else
54 ++it;
55 }
56}
57
58//stable_unique版本2: 谓词判断
59template<typename T,template <typename U> class Predicate>
60void stable_unique(std::vector<T>& con)
61{
62 std::vector<T>::iterator it,ret,beg = con.begin();
63 for (it = ++con.begin();it!=con.end();)
64 {
65 ret = find_if(beg,it,Predicate<T>(*it));
66 if (ret != it)
67 it = con.erase(it);
68 else
69 ++it;
70 }
71}
展开全部
你好!
上面几位大牛已经说到原因了,我来说下解决方法。
使用erase函数的时候要特别小心,使用方法应该如下:iter2 = ver.erase(iter2);
因为按照你的代码的意思,删除之后,迭代器指向删除元素的后一元素,但是erase函数里面并没有完成后移的工作,而是用了返回下一元素迭代器的方式。
希望我的回答能对你有所帮助!
如果满意记得采纳为最佳答案哦!~
如果还有问题,可以BaiduHi我,O(∩_∩)O~!
上面几位大牛已经说到原因了,我来说下解决方法。
使用erase函数的时候要特别小心,使用方法应该如下:iter2 = ver.erase(iter2);
因为按照你的代码的意思,删除之后,迭代器指向删除元素的后一元素,但是erase函数里面并没有完成后移的工作,而是用了返回下一元素迭代器的方式。
希望我的回答能对你有所帮助!
如果满意记得采纳为最佳答案哦!~
如果还有问题,可以BaiduHi我,O(∩_∩)O~!
本回答被提问者采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
有可能。比如插入元素后,有可能会使vector的size超过现在的capacity,这时就有可能会重新分配一块更大的内存,把原来的东西复制过来。这时老的迭带器就指向一块无效的内存了。
所以最好不要在遍历时插入/删除元素。
所以最好不要在遍历时插入/删除元素。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
iter2++;
你这么++很容易超出边界的,检查一下。
要删掉一个元素,建议先得到前一个元素的指针,然后再删除,最后++
你这么++很容易超出边界的,检查一下。
要删掉一个元素,建议先得到前一个元素的指针,然后再删除,最后++
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询