C++ 容器使用指南
一.迭代器
当使用 C++ 中的容器(如
std::vector
、std::list
、std::map
等)时,迭代器是一种非常重要的工具它们提供了一种通用的方式来访问容器中的元素,允许我们对容器进行遍历、访问、修改和删除操作
1.开始和结束迭代器
begin()
:返回指向容器第一个元素的迭代器end()
:返回指向容器尾部(最后一个元素的下一个位置)的迭代器
#include <iostream>
#include <vector>
int main() {std::vector<int> vec = {1, 2, 3, 4, 5};// 使用迭代器遍历容器for (auto it = vec.begin(); it != vec.end(); ++it) {std::cout << *it << " ";}std::cout << std::endl;return 0;
}
2.解引用迭代器
*it
:解引用迭代器,获取迭代器指向的元素的值
std::vector<int> vec = {1, 2, 3, 4, 5};
auto it = vec.begin();
std::cout << *it << std::endl; // 输出第一个元素的值
3.向容器中插入和删除元素
insert(it, value)
:在迭代器位置插入元素erase(it)
:删除迭代器指向的元素
std::vector<int> vec = {1, 2, 3, 4, 5};
auto it = vec.begin() + 2; // 迭代器指向第三个元素
// 在迭代器位置插入元素
vec.insert(it, 10);
// 删除迭代器指向的元素
vec.erase(it);
4. 自增和自减操作
++it
:迭代器自增,指向下一个元素--it
:迭代器自减,指向前一个元素
5. 检查迭代器是否有效
it != container.end()
:迭代器不等于容器的结束迭代器,表示迭代器有效it == container.end()
:迭代器等于容器的结束迭代器,表示迭代器无效(已经遍历到容器末尾)
三.动态数组(Vector)(向量)
- 特点
- 动态数组,支持随机访问
- 连续内存存储,支持快速的随机访问和插入删除末尾元素
- 自动扩展容量,但当容量不够时需要重新分配内存,可能导致性能开销。
- 注意事项
- 插入和删除操作在末尾较高效,在中间或头部可能效率较低
- 当需要频繁在中间位置插入或删除元素时,考虑使用其他容器,如双向链表
1.头文件:
#include <vector>
2.创建和初始化向量
使用 std::vector
来定义一个向量,可以指定元素类型,也可以不指定类型,默认构造一个空向量
vector<int> myVector; // 定义一个整数类型的向量,默认为空
vector<int> myVector2(5); // 定义一个包含5个元素的整数向量,初始值为0
vector<int> myVector3 = {1, 2, 3, 4, 5}; // 初始化一个包含元素的向量
3.添加元素到向量末尾
使用 push_back
函数将元素添加到向量的末尾
myVector.push_back(10);
myVector.push_back(20);
myVector.push_back(30);
// myVector: [10, 20, 30]
4.访问和修改元素
可以使用下标操作符 []
来访问向量中的元素,也可以使用 at()
函数来访问指定位置的元素。使用这些方式也可以修改元素的值
int firstElement = myVector[0]; // 访问第一个元素
int secondElement = myVector.at(1); // 访问第二个元素
myVector[2] = 35; // 修改第三个元素的值为 35
5.获取向量大小
使用 size()
函数来获取向量中元素的数量
cout << "Size of myVector: " << myVector.size() << endl; // 输出 3
6.迭代访问
可以使用迭代器来遍历向量中的元素
for (auto it = myVector.begin(); it != myVector.end(); ++it) {cout << *it << " ";
}
cout << endl;
也可以使用范围-based for 循环来遍历
for (int num : myVector) {cout << num << " ";
}
cout << endl;
7.删除元素
- 使用
pop_back()
函数删除向量末尾的元素
myVector.pop_back(); // 删除末尾的元素
// myVector: [10, 20]
- 使用
erase()
函数删除指定位置的元素
myVector.erase(myVector.begin() + 1); // 删除第二个元素
// myVector: [10]
8.清空向量
使用 clear()
函数清空向量中的所有元素
Vector.clear(); // 清空向量
// myVector: []
三.哈希表(映射)(Map)
- 特点
- 存储键值对的容器
- 键是唯一的,值可以重复。
- 通过键快速查找对应的值
- 注意事项
- 插入相同键的元素会覆盖原来的值
- 查找元素的时间复杂度为 O(log n),插入和删除操作的时间复杂度也为 O(log n)
1.包文件
#include <unordered_map>
1.创建和初始化
#include <iostream>
unordered_map<std::string, int> myMap = {{"apple", 5},{"banana", 3},{"cherry", 7}
};
2.插入和访问元素
insert({key, value})
:插入键值对operator[]
:访问或设置元素值
myMap.insert({"date", 10}); // 插入键值对
myMap["grape"] = 4; // 设置元素值// 访问元素
cout << "键值: " << myMap["cherry"] << endl;
3.删除元素
erase(key)
:删除指定键对应的元素
myMap.erase("banana"); // 删除元素
4.检查键是否存在
count(key)
:检查指定键是否存在,返回 1 表示存在,0 表示不存在
if (myMap.count("banana")) {cout << "myMap有Banana" << endl;
} else {cout << "myMap没有Banana" << endl;
}
5.遍历
可以使用迭代器遍历哈希表中的键值对
for (const auto& pair : myMap) {cout << pair.first << " : " << pair.second << endl;
}
6.获取哈希表大小
size()
:返回哈希表中键值对的数量
cout << "Size of myMap: " << myMap.size() << endl;
7.清空哈希表
clear()
:清空哈希表中的所有元素
myMap.clear(); // 清空哈希表
四.双向链表(List)
- 特点
- 每个节点有指向前一个和后一个节点的指针
- 适合频繁在中间位置插入或删除元素
- 不支持随机访问,需要通过迭代器遍历
- 注意事项
- 插入和删除操作效率高,时间复杂度为 O(1)
- 如果需要随机访问元素,考虑使用其他容器,如向量或集合
1.包文件
#include <list>
2.创建和初始化
// 创建一个整型列表
list<int> myList = {1, 2, 3, 4, 5};
3.插入元素
push_back(value)
:在列表末尾插入元素push_front(value)
:在列表头部插入元素insert(iterator, value)
:在指定位置插入元素
myList.push_back(6); // {1, 2, 3, 4, 5, 6}
myList.push_front(0); // {0, 1, 2, 3, 4, 5, 6}
auto it = myList.begin(); // 获取迭代器指向头部
myList.insert(++it, 10); // {0, 10, 1, 2, 3, 4, 5, 6}
4.删除元素
pop_back()
:删除列表末尾元素pop_front()
:删除列表头部元素erase(iterator)
:删除指定位置的元素remove(value)
:删除所有等于指定值的元素
codemyList.pop_back(); // {0, 10, 1, 2, 3, 4, 5}
myList.pop_front(); // {10, 1, 2, 3, 4, 5}
auto it2 = myList.begin();
myList.erase(++it2); // {10, 2, 3, 4, 5}
myList.remove(3); // {10, 2, 4, 5}
5.访问元素
- 使用迭代器遍历列表元素
begin()
返回指向列表第一个元素的迭代器end()
返回指向列表末尾(最后一个元素的下一个位置)的迭代器
// 遍历列表
for (auto it = myList.begin(); it != myList.end(); ++it) {cout << *it << " ";
}
cout << endl;// 反向遍历列表
for (auto rit = myList.rbegin(); rit != myList.rend(); ++rit) {std::cout << *rit << " ";
}
cout << endl;
6.获取列表大小
cout << "列表的大小: " << myList.size() << endl;
size()
:返回列表中元素的数量
7.清空列表
myList.clear(); // {}
clear()
:清空列表中所有元素
五.集合 (Set)
- 特点
- 存储一组不重复元素的容器
- 自动排序(有序集合)或无序(无序集合)
- 支持快速查找、插入和删除操作
- 注意事项
- 插入相同键的元素会覆盖原来的值
- 查找元素的时间复杂度为 O(log n),插入和删除操作的时间复杂度也为 O(log n)
1.包文件
#include <set>
2.创建和初始化
// 创建一个整型集合
set<int> mySet = {4, 2, 1, 3, 5};
3.插入元素
insert(value)
:插入一个元素到集合中。
mySet.insert(6); // {1, 2, 3, 4, 5, 6}
4.删除元素
erase(value)
:删除指定值的元素。erase(iterator)
:通过迭代器删除元素。
mySet.erase(3); // {1, 2, 4, 5, 6}
5.查找元素
find(value)
:查找指定值的元素,返回指向该元素的迭代器。如果不存在,返回end()
。
auto it = mySet.find(4);
if (it != mySet.end()) {cout << "查询:" << *it << endl;
} else {cout << "未查询到" << endl;
}
6.遍历集合
for (auto it = mySet.begin(); it != mySet.end(); ++it) {std::cout << *it << " ";
}
cout << endl;
7.获取集合大小
size()
:返回集合中元素的数量。
cout << "集合的大小: " << mySet.size() <<endl;
8.清空集合
clear()
:清空集合中所有元素。
mySet.clear();
六.堆栈 (Stack)
- 特点
- 后进先出(LIFO)的数据结构。
- 只能在顶部添加和删除元素。
- 用于函数调用、表达式求值等场景。
- 注意事项
- 使用
top()
前需确保堆栈非空,否则可能会导致未定义行为。 - 操作堆栈的时间复杂度为 O(1)。
- 使用
1.包文件
#include <stack>
2.创建和初始化
stack<int> myStack;
3.基本操作
push(value)
:将元素压入堆栈的顶部pop()
:从堆栈顶部移除元素top()
:获取堆栈顶部的元素
myStack.push(1);
myStack.push(2);
myStack.push(3);// myStack: [1, 2, 3]int topElement = myStack.top(); // 获取顶部元素,topElement = 3myStack.pop(); // 移除顶部元素// myStack: [1, 2]
4.检查堆栈是否为空
empty()
:如果堆栈为空,返回true
,否则返回false
if (myStack.empty()) {cout << "堆栈为空." << endl;
} else {cout << "堆栈不为空" << endl;
}
5.获取堆栈大小
size()
:返回堆栈中元素的数量。
cout << "堆栈的大小: " << myStack.size() << endl;
七. 队列 (Queue)
- 特点
- 先进先出(FIFO)的数据结构
- 只能在队尾添加元素,在队首移除元素
- 用于任务调度、广度优先搜索等场景
- 注意事项
- 当队列为空时,尝试访问头部元素或移除元素会导致未定义行为
- 操作队列的时间复杂度为 O(1)
1.包文件
#include <queue>
2.创建和初始化
queue<int> myQueue;
3.基本操作
push(value)
:将元素压入队列的末尾pop()
:从队列的头部移除元素front()
:获取队列头部的元素值back()
:获取队列末尾的元素值
myQueue.push(1);
myQueue.push(2);
myQueue.push(3);// myQueue: [1, 2, 3]int frontElement = myQueue.front(); // 获取头部元素,frontElement = 1
int backElement = myQueue.back(); // 获取末尾元素,backElement = 3myQueue.pop(); // 移除头部元素// myQueue: [2, 3]
4.检查队列是否为空
empty()
:如果队列为空,返回true
,否则返回false
。
if (myQueue.empty()) {cout << "队列为空" << endl;
} else {cout << "队列不为空" << endl;
}
5.获取队列大小
size()
:返回队列中元素的数量。
cout << "队列大小:" << myQueue.size() << endl;
后记
感谢读者阅读并关注博客文章,并对文章中提到的观点、建议或批评表示感谢✨✨✨