我在做一道贪心算法的练习题,其中一部分是为了遍历vector,然后把里面符合要求的部分删除,但是却报了奇怪的错误。我稍微改了一下,错误解决了,但我搞不清楚错误的原因。希望有大神能给我一些建议。
不要网上的答案,我只要针对我这个具体问题的错误原因。
出错的部分:
vector<struct dianshi>::iterator it2 = ds.begin();
while (it2 != ds.end()) {
//外面的大循环进行到第三轮,在这里报错了
if (it2!=min_it&& (*it2).start_time < min) {
it2 = ds.erase(it2);//删除元素,返回值指向已删除元素的下一个位置
}
else {
it2++;
}
}
ds.erase(min_it);
}
测试用例:
12
1 3
3 4
0 7
3 8
15 19
15 20
10 15
8 18
6 12
5 10
4 14
2 9
下面是两个源代码
错误的代码:
#include<iostream>
#include<vector>
#include<iterator>
using namespace std;
struct dianshi {
int start_time, end_time;
};
int main() {
int num;
while (cin >> num&&num!=0) {
int cnt = 0;
vector<struct dianshi> ds;
while (num--) {
struct dianshi a;
cin >> a.start_time >> a.end_time;
ds.push_back(a);
}
while (!ds.empty()) {
cnt++;
int min = ds.front().end_time;
vector<struct dianshi>::iterator min_it = ds.begin();
//找到那个结束时间最早的
for (vector<struct dianshi>::iterator it = ds.begin(); it != ds.end(); it++) {
if ((*it).end_time < min) {
min = (*it).end_time;
min_it = it;
}
}
//删除开始时间比这个结束时间早的所有。
vector<struct dianshi>::iterator it2 = ds.begin();
while (it2 != ds.end()) {
//外面的大循环进行到第三轮,在这里报错了
if (it2!=min_it&& (*it2).start_time < min) {
it2 = ds.erase(it2);//删除元素,返回值指向已删除元素的下一个位置
}
else {
it2++;
}
}
ds.erase(min_it);
}
cout << cnt;
}
system("pause");
}
改正后的代码
#include<iostream>
#include<vector>
#include<iterator>
using namespace std;
struct dianshi {
int start_time, end_time;
};
int main() {
int num;
while (cin >> num&&num!=0) {
int cnt = 0;
vector<struct dianshi> ds;
while (num--) {
struct dianshi a;
cin >> a.start_time >> a.end_time;
ds.push_back(a);
}
while (!ds.empty()) {
cnt++;
int min = ds.front().end_time;
vector<struct dianshi>::iterator min_it = ds.begin();
//找到那个结束时间最早的
for (vector<struct dianshi>::iterator it = ds.begin(); it != ds.end(); it++) {
if ((*it).end_time < min) {
min = (*it).end_time;
min_it = it;
}
}
//删除开始时间比这个结束时间早的所有。
ds.erase(min_it);
vector<struct dianshi>::iterator it2 = ds.begin();
while ( it2 != ds.end()) {
if ((*it2).start_time < min) {
it2 = ds.erase(it2);//删除元素,返回值指向已删除元素的下一个位置
}
else {
it2++;
}
}
//ds.erase(min_it);
}
cout << cnt;
}
system("pause");
}
删除元素会修改迭代器的状态,导致错误,解决方法是从后往前删除。或者每次删除后,重新迭代。
vector::iterator it2 = ds.begin();
while (it2 != ds.end())
{
if (it2 != min_it && (*it2).start_time < min)
{
it2 = ds.erase(it2);//删除元素,返回值指向已删除元素的下一个位置
}
else
{
it2++;
}
}
ds.erase(min_it);
注意:一旦ds.erase(it2)执行了,那么min_it 这个迭代器就可能失效了(指向vector删除点之后的迭代器会失效)。因此以后的 it2 != min_it 和 ds.erase(min_it) 都是在使用不确定的迭代器,报错是可能发生的。
以上。
在执行完 it2 = ds.erase(it2);之后,迭代器min_it地址已经发生了变化 你再执行 ds.erase(min_it); 语句就会报错误。而你修改后的代码是 先执行ds.erase(min_it),然后再遍历vector执行it2 = ds.erase(it2);。 所以不会出错