C++ 第 17 次课:迭代器与容器的应用
1. 迭代器简介
迭代器提供了一种访问容器元素的通用方法,类似于指针,但更加抽象和安全。它们允许我们遍历容器中的元素,而无需了解容器底层的具体实现。
代码示例 (使用迭代器遍历 vector):
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
// 使用迭代器遍历 vector
for (std::vector<int>::iterator it = numbers.begin(); it != numbers.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
return 0;
}
2. vector
vector
是一个动态数组,可以根据需要自动调整大小。
2.1 添加元素:
push_back(value)
: 在 vector 末尾添加元素。
代码示例:
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers;
numbers.push_back(1);
numbers.push_back(2);
numbers.push_back(3);
for (int i = 0; i < numbers.size(); ++i) {
std::cout << numbers[i] << " ";
}
std::cout << std::endl;
return 0;
}
insert(iterator, value)
: 在指定迭代器位置插入元素。
代码示例:
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers = {1, 3, 4};
std::vector<int>::iterator it = numbers.begin() + 1; // 指向第二个元素 (3)
numbers.insert(it, 2);
for (int i = 0; i < numbers.size(); ++i) {
std::cout << numbers[i] << " ";
}
std::cout << std::endl;
return 0;
}
2.2 删除元素:
pop_back()
: 删除 vector 末尾的元素。
代码示例:
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers = {1, 2, 3};
numbers.pop_back();
for (int i = 0; i < numbers.size(); ++i) {
std::cout << numbers[i] << " ";
}
std::cout << std::endl;
return 0;
}
erase(iterator)
: 删除指定迭代器位置的元素。
代码示例:
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers = {1, 2, 3, 4};
std::vector<int>::iterator it = numbers.begin() + 1; // 指向第二个元素 (2)
numbers.erase(it);
for (int i = 0; i < numbers.size(); ++i) {
std::cout << numbers[i] << " ";
}
std::cout << std::endl;
return 0;
}
2.3 修改元素:
可以使用迭代器直接访问和修改元素。
代码示例:
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers = {1, 2, 3};
std::vector<int>::iterator it = numbers.begin() + 1; // 指向第二个元素 (2)
*it = 5;
for (int i = 0; i < numbers.size(); ++i) {
std::cout << numbers[i] << " ";
}
std::cout << std::endl;
return 0;
}
2.4 查询元素:
可以使用迭代器遍历 vector 并查找特定元素。
代码示例:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
std::vector<int>::iterator it = std::find(numbers.begin(), numbers.end(), 3);
if (it != numbers.end()) {
std::cout << "Found 3 at index: " << std::distance(numbers.begin(), it) << std::endl;
} else {
std::cout << "3 not found." << std::endl;
}
return 0;
}
3. list
list
是一个双向链表,允许在任何位置快速插入和删除元素。
3.1 添加元素:
push_back(value)
: 在 list 末尾添加元素。push_front(value)
: 在 list 开头添加元素。insert(iterator, value)
: 在指定迭代器位置插入元素。
代码示例 (在 list 开头插入元素):
#include <iostream>
#include <list>
int main() {
std::list<int> numbers = {2, 3};
numbers.push_front(1);
for (std::list<int>::iterator it = numbers.begin(); it != numbers.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
return 0;
}
3.2 删除元素:
pop_back()
: 删除 list 末尾的元素。pop_front()
: 删除 list 开头的元素。erase(iterator)
: 删除指定迭代器位置的元素。remove(value)
: 删除所有值为 value 的元素。
代码示例 (删除 list 中所有值为 2 的元素):
#include <iostream>
#include <list>
int main() {
std::list<int> numbers = {1, 2, 3, 2, 4};
numbers.remove(2);
for (std::list<int>::iterator it = numbers.begin(); it != numbers.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
return 0;
}
3.3 修改元素:
可以使用迭代器直接访问和修改元素。
代码示例:
#include <iostream>
#include <list>
int main() {
std::list<int> numbers = {1, 2, 3};
std::list<int>::iterator it = numbers.begin();
std::advance(it, 1); // 移动迭代器到第二个元素 (2)
*it = 5;
for (std::list<int>::iterator iter = numbers.begin(); iter != numbers.end(); ++iter) {
std::cout << *iter << " ";
}
std::cout << std::endl;
return 0;
}
3.4 查询元素:
可以使用迭代器遍历 list 并查找特定元素。
代码示例:
#include <iostream>
#include <list>
#include <algorithm>
int main() {
std::list<int> numbers = {1, 2, 3, 4, 5};
std::list<int>::iterator it = std::find(numbers.begin(), numbers.end(), 3);
if (it != numbers.end()) {
std::cout << "Found 3" << std::endl;
} else {
std::cout << "3 not found." << std::endl;
}
return 0;
}
4. forward_list
forward_list
是一个单向链表,只允许向前遍历。
4.1 添加元素:
push_front(value)
: 在 forward_list 开头添加元素。insert_after(iterator, value)
: 在指定迭代器位置之后插入元素.
代码示例 (在 forward_list 开头插入元素):
#include <iostream>
#include <forward_list>
int main() {
std::forward_list<int> numbers = {2, 3};
numbers.push_front(1);
for (std::forward_list<int>::iterator it = numbers.begin(); it != numbers.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
return 0;
}
4.2 删除元素:
pop_front()
: 删除 forward_list 开头的元素。erase_after(iterator)
: 删除指定迭代器位置之后的元素。remove(value)
: 删除所有值为 value 的元素。
代码示例 (删除 forward_list 开头的元素):
#include <iostream>
#include <forward_list>
int main() {
std::forward_list<int> numbers = {1, 2, 3};
numbers.pop_front();
for (std::forward_list<int>::iterator it = numbers.begin(); it != numbers.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
return 0;
}
4.3 修改元素:
可以使用迭代器直接访问和修改元素。
代码示例:
#include <iostream>
#include <forward_list>
int main() {
std::forward_list<int> numbers = {1, 2, 3};
std::forward_list<int>::iterator it = numbers.begin();
std::advance(it, 1); // 移动迭代器到第二个元素 (2)
*it = 5;
for (std::forward_list<int>::iterator iter = numbers.begin(); iter != numbers.end(); ++iter) {
std::cout << *iter << " ";
}
std::cout << std::endl;
return 0;
}
4.4 查询元素:
可以使用迭代器遍历 forward_list 并查找特定元素。
代码示例:
#include <iostream>
#include <forward_list>
#include <algorithm>
int main() {
std::forward_list<int> numbers = {1, 2, 3, 4, 5};
std::forward_list<int>::iterator it = std::find(numbers.begin(), numbers.end(), 3);
if (it != numbers.end()) {
std::cout << "Found 3" << std::endl;
} else {
std::cout << "3 not found." << std::endl;
}
return 0;
}
5. deque
deque
是一个双端队列,允许在两端快速插入和删除元素。
5.1 添加元素:
push_back(value)
: 在 deque 末尾添加元素。push_front(value)
: 在 deque 开头添加元素。insert(iterator, value)
: 在指定迭代器位置插入元素。
代码示例 (在 deque 开头插入元素):
#include <iostream>
#include <deque>
int main() {
std::deque<int> numbers = {2, 3};
numbers.push_front(1);
for (std::deque<int>::iterator it = numbers.begin(); it != numbers.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
return 0;
}
5.2 删除元素:
pop_back()
: 删除 deque 末尾的元素。pop_front()
: 删除 deque 开头的元素。erase(iterator)
: 删除指定迭代器位置的元素。
代码示例 (删除 deque 开头的元素):
#include <iostream>
#include <deque>
int main() {
std::deque<int> numbers = {1, 2, 3};
numbers.pop_front();
for (std::deque<int>::iterator it = numbers.begin(); it != numbers.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
return 0;
}
5.3 修改元素:
可以使用迭代器直接访问和修改元素。
代码示例:
#include <iostream>
#include <deque>
int main() {
std::deque<int> numbers = {1, 2, 3};
std::deque<int>::iterator it = numbers.begin();
std::advance(it, 1); // 移动迭代器到第二个元素 (2)
*it = 5;
for (std::deque<int>::iterator iter = numbers.begin(); iter != numbers.end(); ++iter) {
std::cout << *iter << " ";
}
std::cout << std::endl;
return 0;
}
5.4 查询元素:
可以使用迭代器遍历 deque 并查找特定元素。
代码示例:
#include <iostream>
#include <deque>
#include <algorithm>
int main() {
std::deque<int> numbers = {1, 2, 3, 4, 5};
std::deque<int>::iterator it = std::find(numbers.begin(), numbers.end(), 3);
if (it != numbers.end()) {
std::cout << "Found 3" << std::endl;
} else {
std::cout << "3 not found." << std::endl;
}
return 0;
}
6. queue
queue
是一个队列,遵循 FIFO (先进先出) 原则。
6.1 添加元素:
push(value)
: 在队列末尾添加元素。
代码示例:
#include <iostream>
#include <queue>
int main() {
std::queue<int> numbers;
numbers.push(1);
numbers.push(2);
numbers.push(3);
while (!numbers.empty()) {
std::cout << numbers.front() << " ";
numbers.pop();
}
std::cout << std::endl;
return 0;
}
6.2 删除元素:
pop()
: 删除队列开头的元素。
代码示例 (参考 6.1)
6.3 访问元素:
front()
: 访问队列开头的元素。back()
: 访问队列末尾的元素。
代码示例 (参考 6.1)
注意: queue
不支持迭代器遍历。
7. set
set
是一个有序集合,不允许重复元素。
7.1 添加元素:
insert(value)
: 在 set 中插入元素。
代码示例:
#include <iostream>
#include <set>
int main() {
std::set<int> numbers;
numbers.insert(3);
numbers.insert(1);
numbers.insert(2);
numbers.insert(2); // 重复元素,不会被插入
for (std::set<int>::iterator it = numbers.begin(); it != numbers.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
return 0;
}
7.2 删除元素:
erase(iterator)
: 删除指定迭代器位置的元素。erase(value)
: 删除值为 value 的元素。
代码示例 (删除值为 2 的元素):
#include <iostream>
#include <set>
int main() {
std::set<int> numbers = {1, 2, 3};
numbers.erase(2);
for (std::set<int>::iterator it = numbers.begin(); it != numbers.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
return 0;
}
7.3 查询元素:
find(value)
: 查找值为 value 的元素,返回指向该元素的迭代器,如果未找到则返回end()
。
代码示例:
#include <iostream>
#include <set>
int main() {
std::set<int> numbers = {1, 2, 3, 4, 5};
std::set<int>::iterator it = numbers.find(3);
if (it != numbers.end()) {
std::cout << "Found 3" << std::endl;
} else {
std::cout << "3 not found." << std::endl;
}
return 0;
}
注意: set
中的元素是 const 的,不能通过迭代器修改。
8. map
map
是一个键值对的集合,键是唯一的。
8.1 添加元素:
insert(std::pair<key, value>)
: 插入一个键值对。[key] = value
: 通过键访问并赋值。
代码示例:
#include <iostream>
#include <map>
int main() {
std::map<std::string, int> ages;
ages.insert(std::pair<std::string, int>("Alice", 25));
ages["Bob"] = 30;
for (std::map<std::string, int>::iterator it = ages.begin(); it != ages.end(); ++it) {
std::cout << it->first << ": " << it->second << std::endl;
}
return 0;
}
8.2 删除元素:
erase(iterator)
: 删除指定迭代器位置的元素。erase(key)
: 删除键为 key 的元素。
代码示例 (删除键为 "Bob" 的元素):
#include <iostream>
#include <map>
int main() {
std::map<std::string, int> ages;
ages["Alice"] = 25;
ages["Bob"] = 30;
ages.erase("Bob");
for (std::map<std::string, int>::iterator it = ages.begin(); it != ages.end(); ++it) {
std::cout << it->first << ": " << it->second << std::endl;
}
return 0;
}
8.3 修改元素:
可以使用迭代器或键访问并修改值。
代码示例 (修改 "Alice" 的年龄):
#include <iostream>
#include <map>
int main() {
std::map<std::string, int> ages;
ages["Alice"] = 25;
ages["Bob"] = 30;
ages["Alice"] = 26;
for (std::map<std::string, int>::iterator it = ages.begin(); it != ages.end(); ++it) {
std::cout << it->first << ": " << it->second << std::endl;
}
return 0;
}
8.4 查询元素:
find(key)
: 查找键为 key 的元素,返回指向该元素的迭代器,如果未找到则返回end()
。
代码示例:
#include <iostream>
#include <map>
int main() {
std::map<std::string, int> ages;
ages["Alice"] = 25;
ages["Bob"] = 30;
std::map<std::string, int>::iterator it = ages.find("Bob");
if (it != ages.end()) {
std::cout << "Bob's age: " << it->second << std::endl;
} else {
std::cout << "Bob not found." << std::endl;
}
return 0;
}
作业
请自行选择内部数据结构设计一 个 stack 的模板类
template <typename T>
struct MyStack {
MyStack() {
}
void push(const T& t) {
stack_inside_.push_back(t);
}
T top() {
return stack_inside_.back();
}
void pop() {
return stack_inside_.pop_back();
}
bool empty() {
return stack_inside_.empty();
}
std::vector<T> stack_inside_;
};
int main() {
MyStack<int> stack;
Stack.push(1);
stack.push(2);
if (!stack.empty()) {
std::cout << stack.top() << std::endl;
}
Stack.pop();
}