信奥竞赛

系列

剑指信奥 | C++ 之 STL - 算法 remove

剑指信奥 |C++ 之 STL 算法 remove

不想给你看的,就藏起来吧

修改序列的算法

今天,我们开始了解一下算法类别中,可以修改序列的算法。

修改序列的算法有很多,这些算法的共同点是都对序列做了各种各样的改变,我们今天从比较简单的 remove 删除 算法开始。

remove

remove() 函数的作用是从指定范围内「删除」指定值的元素。

这个函数接收 3 个参数:

  1. 起始元素的正向迭代器 first
  2. 终止元素的后一个元素的正向迭代器 last
  3. 要删除的值 value

代码示例:

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

int main() {

vector<int> vi = {1, 2, 3, 3, 3};

// 声明迭代器
vector<int>::iterator first, last, end;

// 区间范围是 [first, last)
first = vi.begin();
last = vi.end();

// 要删除的值
int value = 3;

// 调用 remove 函数
end = remove(first, last, value);

// 输出 vi
for (auto i = first; i != end; ++i) {
cout << *i << "\t";
}

// 输出 vi 的 size
cout << endl << "vi.size() = " << vi.size() << endl;

return 0;
}

/*
output
1 2
vi.size() = 5
*/

上面的代码展示了 remove() 函数的使用,我们从一个 vector 中删除了指定的元素 3。

第一行输出的结果符合我们的预期,元素 3 没有了,但是问题出现在输出语句的第二行,vi.size() = 5

不是明明删除了三个 3,只剩下了两个元素,为什么 vi 的长度还是 5?

这是 remove() 函数特别需要注意的一点,虽然从字面意思上,remove 的意思是删除,但是并不是真正删除了序列中的元素,而是把这些元素移动到了序列的尾部。

同时,还需注意,这个函数返回的是不含指定元素的序列的尾后迭代器。

所以,在 for 循环中,我们的循环条件并不是 i != last 而是 i != end,而这个 end 正是 remove() 函数返回的迭代器!

remove_if

在切实了解了 remove() 函数的原理后,remove_if() 函数就很简单了。

根据我们前序课程的知识,我们能猜想到,这个函数只不过是多了个一元谓词,根据谓词函数返回 true 来指定要删除的元素。

代码示例:

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

// 一元谓词
inline bool p(int x) {
return x < 3;
}

int main() {

vector<int> vi = {1, 2, 3, 3, 3};

// 声明迭代器
vector<int>::iterator first, last, end;

// 区间范围是 [first, last)
first = vi.begin();
last = vi.end();

// 要删除的值
int value = 3;

// 调用 remove_if 函数
end = remove_if(first, last, p);

// 输出 vi
for (auto i = first; i != end; ++i) {
cout << *i << "\t";
}

// 输出 vi 的 size
cout << endl << "vi.size() = " << vi.size() << endl;

return 0;
}

/*
output
3 3 3
vi.size() = 5
*/

结果棒棒的!

所以,务必记住,remove() 不是丢掉,而是 — 雪藏~