STL(Standard Template Library)容器
vector容器 — 动态数组
简介
vector 是一个序列容器,它允许用户在容器的末尾快速地添加或删除元素。与数组相比,vector提供了更多的功能,如自动调整大小,随机访问等。
语法
在C++中使用vector需要包含头文件“ #include
以下是一些基本语法:
声明vector:
vector<int> myVector; //声明一个int类型的vector myVector
添加元素:
myVector.push_back(10); //在末尾添加一个元素10
访问元素:
int a = myVector[0]; //将0号位的元素赋给a
cout << myVector[0]; //输出0号位的元素
获取元素数量:
int size_myVector = myVector.size();
清空vector:
myVector.clear();
声明与初始化
vector需要制定元素类型,可通过多种方式初始化:
#include <iostream>
#include <vector>
using namespace std;
int main() {vector<int> vec1; // 空的vectorvector<int> vec2(5); // 长度为5的vector,元素默认初始化vector<int> vec3(5, 10); // 长度为5的vector,元素值均为10vector<int> vec4 = {1, 2, 3, 4}; // 使用初始化列表初始化return 0;
}
实例
#include <iostream>
#include <vector>
using namespace std;int main() {// 声明一个存储整数的 vectorvector<int> numbers;// 添加元素numbers.push_back(10);numbers.push_back(20);numbers.push_back(30);// 输出 vector 中的元素cout << "vector中的元素: ";for (int i = 0; i < numbers.size(); ++i) {cout << numbers[i] << " ";}cout << endl;// 添加更多元素numbers.push_back(40);numbers.push_back(50);// 再次输出 vector 中的元素cout << "在添加元素之后, vector中的元素: ";for (int i = 0; i < numbers.size(); ++i) {cout << numbers[i] << " ";}cout << endl;// 访问特定元素cout << "第一个元素: " << numbers[0] << endl;// 清空 vectornumbers.clear();// 检查 vector 是否为空if (numbers.empty()) {cout << "这个vector是空的" << endl;}return 0;
}
运行结果:
vector中的元素: 10 20 30
在添加元素之后, vector中的元素: 10 20 30 40 50
第一个元素: 10
这个vector是空的
常用的成员函数
函数
函数 | 说明 |
---|---|
push_back(const T& val) | 在末尾添加元素 |
pop_back() | 删除末尾元素 |
at(size_t pos) | 返回指定位置的元素,带边界检查 |
operator[ ] | 返回指定位置的元素,不带边界检查 |
front() | 返回第一个元素 |
back() | 返回最后一个元素 |
data() | 返回指向底层数组的指针 |
size() | 返回当前元素数量 |
capacity() | 返回当前分配的容量 |
reserve(size_t n) | 预留至少n个元素的储存空间 |
resize(size_t n) | 将元素数量调整为n |
clear() | 清空所有元素 |
insert(iterator pos, val) | 在指定位置插入元素 |
erase(iterator pos) | 删除指定位置的元素 |
begin()/end() | 返回起始/结束迭代器 |
实例
1.基本操作
#include <iostream>
#include <vector>
using namespace std;int main() {vector<int> vec = {1, 2, 3, 4, 5};// 输出所有元素cout << "vector中的元素: ";for (int i = 0; i < vec.size(); ++i) {cout << vec[i] << " ";}cout << endl;// 获取第一个和最后一个元素cout << "第一个元素: " << vec.front() << endl;cout << "最后一个元素: " << vec.back() << endl;return 0;
}
运行结果:
vector中的元素: 1 2 3 4 5
第一个元素: 1
最后一个元素: 5
2.动态增加和删除元素
#include <iostream>
#include <vector>
using namespace std;int main() {vector<int> vec;vec.push_back(10);vec.push_back(20);vec.push_back(30);cout << "vector元素数量: " << vec.size() << endl;cout << "vector当前分配的容量: " << vec.capacity() << endl;// 删除最后一个元素vec.pop_back();cout << "删除最后一个元素后的vector大小: " << vec.size() << endl;return 0;
}
运行结果:
vector元素数量: 3
vector当前分配的容量: 4
删除最后一个元素后的vector大小: 2
3.边界检查和安全访问
#include <iostream>
#include <vector>
using namespace std;int main() {vector<int> vec = {1, 2, 3};try {cout << vec.at(2) << endl; // 正常输出cout << vec.at(5) << endl; // 超出范围,抛出异常} catch (const out_of_range& e) {cout << "Exception: " << e.what() << endl;}return 0;
}
运行结果:
vector元素数量: 3
vector当前分配的容量: 4
删除最后一个元素后的vector大小: 2
4.预分配容量
#include <iostream>
#include <vector>
using namespace std;int main() {vector<int> vec;vec.reserve(10); // 预留容量,避免频繁分配内存for (int i = 0; i < 10; ++i) {vec.push_back(i);cout << "push_back(" << i << ")之后vec当前分配的容量: " << vec.capacity() << endl;}return 0;
}
运行结果:
push_back(0)之后vec当前分配的容量: 10
push_back(1)之后vec当前分配的容量: 10
push_back(2)之后vec当前分配的容量: 10
push_back(3)之后vec当前分配的容量: 10
push_back(4)之后vec当前分配的容量: 10
push_back(5)之后vec当前分配的容量: 10
push_back(6)之后vec当前分配的容量: 10
push_back(7)之后vec当前分配的容量: 10
push_back(8)之后vec当前分配的容量: 10
push_back(9)之后vec当前分配的容量: 10
队列 — queue
C++ 标准库中的
队列是一种线性数据结构,它遵循以下规则:
1.元素只能从队尾添加
2.元素只能从队首移除
语法
#include <queue>// 声明队列
std::queue<Type> q;
常用操作
队列提供了以下常用操作:
empty(): 检查队列是否为空
size(): 返回队列中的元素数量
front(): 返回队首元素的引用
back(): 返回队尾元素的引用
push(): 在队尾添加一个元素
pop(): 移除队首元素
实例
#include <iostream>
#include <queue>int main() {// 创建一个整数队列std::queue<int> q;// 向队列中添加元素q.push(10);q.push(20);q.push(30);// 打印队列中的元素数量std::cout << "队列中的元素数量: " << q.size() << std::endl;// 打印队首元素std::cout << "队首元素: " << q.front() << std::endl;// 打印队尾元素std::cout << "队尾元素: " << q.back() << std::endl;// 移除队首元素q.pop();std::cout << "移除队首元素后,队首元素: " << q.front() << std::endl;// 再次打印队列中的元素数量std::cout << "队列中的元素数量: " << q.size() << std::endl;return 0;
}
运行结果:
队列中的元素数量: 3
队首元素: 10
队尾元素: 30
移除队首元素后,队首元素: 20
队列中的元素数量: 2
C++ 的
注意事项
队列不允许随机访问元素,即不能直接通过索引访问队列中的元素
队列的实现通常使用链表或动态数组,这取决于具体的实现
链表(双向链表)— list
简介
list是 C++ 标准模板库(STL)中的一个序列容器,它允许在容器的任意位置快速插入和删除元素。与数组或向量(vector)不同,list不需要在创建时指定大小,并且可以在任何位置添加或删除元素,而不需要重新分配内存。
语法
基本操作:
包含头文件:#include
声明列表:list
插入元素:mylist.push_back(value);
删除元素:mylist.pop_back(); 或 mylist.erase(iterator);
访问元素:mylist.front(); 和 mylist.begin();
遍历列表:使用迭代器 for(auto it = mylist.begin(); it != mylist.end(); ++ it)
特点
双向迭代 :list提供了双向迭代器,可以向前和向后遍历元素
动态大小 :与数组不同,list的大小可以动态变化,不需要预先分配固定大小的内存
快速插入和删除 :可以在列表的任何位置快速插入或删除元素,而不需要像向量那样移动大量元素
声明与初始化
#include <iostream>
#include <list>
using namespace std;
int main() {list<int> lst1; // 空的listlist<int> lst2(5); // 包含5个默认初始化元素的listlist<int> lst3(5, 10); // 包含5个元素,每个元素为10list<int> lst4 = {1, 2, 3, 4}; // 使用初始化列表return 0;
}
实例
#include <iostream>
#include <list>int main() {// 创建一个整数类型的列表std::list<int> numbers;// 向列表中添加元素numbers.push_back(10);numbers.push_back(20);numbers.push_back(30);// 访问并打印列表的第一个元素std::cout << "第一个元素: " << numbers.front() << std::endl;// 访问并打印列表的最后一个元素std::cout << "最后一个元素: " << numbers.back() << std::endl;// 遍历列表并打印所有元素std::cout << "List的所有元素: ";for (auto it = numbers.begin(); it != numbers.end(); ++it) {std::cout << *it << " ";}std::cout << std::endl;// 删除列表中的最后一个元素numbers.pop_back();// 再次遍历列表并打印所有元素std::cout << "在删除最后一个元素后List的所有元素: ";for (auto it = numbers.begin(); it != numbers.end(); ++it) {std::cout << *it << " ";}std::cout << std::endl;return 0;
}
运行结果:
第一个元素: 10
最后一个元素: 30
List的所有元素: 10 20 30
在删除最后一个元素后List的所有元素: 10 20
成员函数
函数 | 说明 |
---|---|
push_back(const T& val) | 在链表末尾插入元素 |
push_front(const T& val) | 在链表头部添加元素 |
pop_back() | 删除链表末尾的元素 |
pop_front() | 删除链表头部的元素 |
insert(iterator pos, val) | 在指定位置插入元素 |
erase(iterator pos) | 删除指定位置的元素 |
clear() | 清空所有元素 |
size() | 返回链表中的元素数量 |
empty() | 检查链表是否为空 |
front() | 返回链表第一个元素 |
back() | 返回链表最后一个元素 |
remove(const T& val) | 删除所有等于指定值的元素 |
sort() | 对链表中的元素进行排序 |
merge(list& other) | 合并另一个已排序的链表 |
reverse() | 反转链表 |
begin()/end() | 返回链表的起始/结束迭代器 |
实例
1.基本操作
#include <iostream>
#include <list>int main() {std::list<int> lst = {10, 20, 30};// 插入和删除元素lst.push_front(5); // 在头部插入5lst.push_back(40); // 在尾部插入40lst.pop_front(); // 删除头部元素lst.pop_back(); // 删除尾部元素// 输出链表内容std::cout << "链表元素: ";for (const auto& elem : lst) {std::cout << elem << " ";}std::cout << std::endl;return 0;
}
运行结果:
链表元素: 10 20 30
2.插入和删除特定位置的元素
#include <iostream>
#include <list>int main() {std::list<int> lst = {1, 2, 3, 4, 5};auto it = lst.begin();std::advance(it, 2); // 移动迭代器到第3个元素(值为3)lst.insert(it, 10); // 在第3个元素前插入10lst.erase(it); // 删除第3个元素// 输出链表内容std::cout << "链表元素: ";for (const auto& elem : lst) {std::cout << elem << " ";}std::cout << std::endl;return 0;
}
运行结果:
链表元素: 1 2 10 4 5
3.排序和去重
#include <iostream>
#include <list>int main() {std::list<int> lst = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5};lst.sort(); // 排序lst.unique(); // 删除相邻重复元素// 输出链表内容std::cout << "排序去重后的链表: ";for (const auto& elem : lst) {std::cout << elem << " ";}std::cout << std::endl;return 0;
}
运行结果:
排序去重后的链表: 1 2 3 4 5 6 9
4.合并和反转
#include <iostream>
#include <list>int main() {std::list<int> lst1 = {1, 3, 5, 7};std::list<int> lst2 = {2, 4, 6, 8};lst1.merge(lst2); // 合并两个已排序的链表lst1.reverse(); // 反转链表// 输出链表内容std::cout << "合并反转后的链表: ";for (const auto& elem : lst1) {std::cout << elem << " ";}std::cout << std::endl;return 0;
}
运行结果;
合并反转后的链表: 8 7 6 5 4 3 2 1
注意事项
的元素是按插入顺序存储的,而不是按元素值排序。
由于 的元素存储在不同的内存位置,所以它不适合需要随机访问的场景。
与向量相比, 的内存使用效率较低,因为每个元素都需要额外的空间来存储指向前后元素的指针。
栈 — stack
在 C++ 中,标准库提供了多种容器和算法来帮助开发者更高效地编写程序。
基本操作
push(): 在栈顶添加一个元素
pop(): 移除栈顶元素
top(): 返回栈顶元素的引用,但不移除它
empty(): 检查栈是否为空
size(): 返回栈中元素的数量
语法
#include <iostream>
#include <stack>int main() {std::stack<int> s;// 向栈中添加元素s.push(10);s.push(20);s.push(30);// 打印栈顶元素std::cout << "栈顶元素是: " << s.top() << std::endl; // 移除栈顶元素s.pop();std::cout << "移除栈顶元素后,栈顶元素是: " << s.top() << std::endl; // 检查栈是否为空if (!s.empty()) {std::cout << "这个栈不是空的" << std::endl; }// 打印栈的大小std::cout << "栈的大小(元素数量)为: " << s.size() << std::endl; // 继续移除元素s.pop();s.pop();// 检查栈是否为空if (s.empty()) {std::cout << "这个栈是空的" << std::endl; }return 0;
}
运行结果:
栈顶元素是: 30
移除栈顶元素后,栈顶元素是: 20
这个栈不是空的
栈的大小(元素数量)为: 2
这个栈是空的
注意事项
尝试在空栈上调用 top() 或 pop() 将导致未定义行为
map容器
在 C++ 中,
map 容器中的元素是按照键的顺序自动排序的,这使得它非常适合需要快速查找和有序数据的场景。
定义和特性
键值对:map 存储的是键值对,其中每个键都是唯一的。
排序:map 中的元素按照键的顺序自动排序,通常是升序。
唯一性:每个键在 map 中只能出现一次。
双向迭代器:map 提供了双向迭代器,可以向前和向后遍历元素。
基本语法
包含头文件:
#include <map>
声明map容器:
std::map<key_type, value_type> myMap;
key_type 是键的类型。
value_type 是值的类型。
插入元素:
myMap[key] = value;
访问元素:
value = myMap[key];
遍历map:
for (std::map<key_type, value_type>::iterator it = myMap.begin(); it != myMap.end(); ++it) {std::cout << it->first << " => " << it->second << std::endl;
}
实例
下面是一个使用 map 的简单实例,我们将创建一个 map 来存储员工的姓名和他们的年龄,并遍历这个 map 来打印每个员工的姓名和年龄。
#include <iostream>
#include <map>
#include <string>int main() {// 创建一个 map 容器,存储员工的姓名和年龄std::map<std::string, int> employees;// 插入员工信息employees["Alice"] = 30;employees["Bob"] = 25;employees["Charlie"] = 35;// 遍历 map 并打印员工信息for (std::map<std::string, int>::iterator it = employees.begin(); it != employees.end(); ++it) {std::cout << it->first << " 是 " << it->second << " 岁. " << std::endl;}return 0;
}
运行结果:
Alice 是 30 岁.
Bob 是 25 岁.
Charlie 是 35 岁.
看到这个你是不是联想到了结构体?
hhh,这两个有相似的地方也有不同的地方 ,注意自己总结区分哦
进阶用法
检查键是否存在:
if (myMap.find(key) != myMap.end()) {// 键存在
}
删除元素:
myMap.erase(key);
清空map:
myMap.clear();
获取map大小:
size_t size = myMap.size(); //size_t是一种没有符号的整数类型
使用自定义比较函数:
#include <map>
#include <string>
#include <functional>bool myCompare(const std::string& a, const std::string& b) {return a < b;
}int main() {std::map<std::string, int, std::function<bool(const std::string&, const std::string&)>> myMap(myCompare);// 其他操作...return 0;
}
map 是 C++ STL 中一个非常有用的容器,特别适合需要快速查找和有序数据的场景。