C++ STL标准模板库使用

C++ STL标准模板库使用

在线手册参考

C++ STL(标准模板库)是一组标准的 C++ 库,包含了许多常用的数据结构和算法,可大大提高开发效率。以下是常用的 STL 组件:

  1. 容器(Containers):用于存储和管理数据的类模板。常用的容器有:
  • vector:动态数组
  • list:双向链表
  • deque:双端队列
  • set/multiset:集合/多重集合,内部自动排序
  • map/multimap:映射/多重映射,内部自动排序
  • stack:栈
  • queue:队列
  1. 迭代器(Iterators):用于遍历容器中的元素,支持类似指针的操作。
  2. 算法(Algorithms):用于处理容器中的元素,包括查找、排序、删除、替换等。
  3. 函数对象(Function Objects):可用于在算法中进行自定义操作的函数对象。
  4. 数值(Numeric):包含一些数学函数和算法,如求和、平均数、中位数等。
  5. 适配器(Adapters):用于将一种容器或迭代器适配成另一种容器或迭代器,常用的适配器有:
  • stack:用于将 deque 或 list 适配成栈
  • queue:用于将 deque 或 list 适配成队列
  • priority_queue:用于将 vector 或 deque 适配成优先队列

vector

在 C++ STL 中,vector 是一个动态数组容器,它可以自动调整大小以适应元素数量的变化。

常用操作如下:

创建

#include <vector>

// 创建一个空的 vector
std::vector<int> vec;

// 创建一个含有 10 个元素,每个元素都是 0 的 vector
std::vector<int> vec1(10);

// 创建一个含有 10 个元素,每个元素都是 1 的 vector
std::vector<int> vec2(10, 1);

// 创建一个含有 3 个元素,值分别是 1,2,3 的 vector
std::vector<int> vec3 = {1, 2, 3};

// 使用迭代器创建 vector
std::vector<int> vec4(vec3.begin(), vec3.end());

注意:也可以在堆创建vector,不过会比在栈存取数据慢些

vector<int> *vec = new vector<int>{1,2,3};

std::vector<int> vec = {1, 2, 3};

// 在末尾添加一个元素 4
vec.push_back(4);

// 在位置 1 处插入元素 5
vec.insert(vec.begin() + 1, 5);

// 在末尾插入另一个 vector 的所有元素
std::vector<int> vec2 = {6, 7, 8};
vec.insert(vec.end(), vec2.begin(), vec2.end());

std::vector<int> vec = {1, 2, 3, 4, 5};

// 删除末尾的元素
vec.pop_back();

// 删除位置 2 的元素
vec.erase(vec.begin() + 2);

// 删除位置 1 到 3 的元素
vec.erase(vec.begin()+1, vec.begin()+4);

改/查

使用 [] 运算符和 at() 方法都可以访问 vector 中的元素,不同之处在于:

  • 如果使用 [] 运算符访问超出 vector 范围的元素,程序将出现未定义行为

  • 而使用 at() 方法访问超出 vector 范围的元素,程序将抛出 std::out_of_range 异常。

vec[2] // 访问第2个元素
vec.at(3) // 访问第3个元素

vec[2] = 1 // 修改第2个元素值为1
vec.at(3) = 1 // 修改第3个元素值为1

或者使用迭代器访问、修改

vector<int> vec{1, 2, 3, 4, 5};

// 使用迭代器遍历 vector 中的元素
for (auto it = vec.begin(); it != vec.end(); ++it) {
    cout << *it << " ";
}
// 使用迭代器修改 vector 中的元素
for (auto it = vec.begin(); it != vec.end(); ++it) {
    *it += 1;
}
// 使用范围 for 循环输出修改后的 vector 中的元素
for (auto x : vec) {
    cout << x << " ";
}

list

C++ STL 中的 list 是一个双向链表,可以在任意位置进行插入和删除操作,而不会影响其他元素的位置。以下是 list 的常用用法

创建

#include <list>

std::list<int> myList; // 创建一个空的 list
std::list<int> myList = {1, 2, 3, 4, 5}; // 创建包含 1, 2, 3, 4, 5 的 list

  • push_back(value):在 list 尾部插入一个元素。
  • push_front(value):在 list 头部插入一个元素。
  • insert(pos, value):在指定位置插入一个元素。

  • erase(pos):删除指定位置的元素。
  • erase(start, end):删除从 start 到 end 之间的元素。

示例代码:

#include <list>
#include <iostream>

int main() {
    std::list<int> myList = {1, 2, 3};
    myList.push_back(4); // 在尾部插入 4
    myList.push_front(0); // 在头部插入 0
    myList.insert(++myList.begin(), 5); // 在第二个位置插入 5
    myList.erase(--myList.end()); // 删除最后一个元素
    myList.erase(myList.begin(), myList.begin() + 2); // 删除前两个元素

    for (int i : myList) {
        std::cout << i << " "; // 输出: 2 5 4
    }
    return 0;
}

改/查

可以使用以下方法访问 list 中的元素:

  • front():返回 list 的第一个元素。
  • back():返回 list 的最后一个元素。

迭代器法:

// 使用迭代器遍历 list 中的元素
for (auto it = lst.begin(); it != lst.end(); ++it) {
    cout << *it << " ";
}
cout << endl;

// 使用迭代器修改 list 中的元素
for (auto it = lst.begin(); it != lst.end(); ++it) {
    *it += 1;
}

// 使用范围 for 循环输出修改后的 list 中的元素
for (auto x : lst) {
    cout << x << " ";
}

list不能像 vector 那样使用索引或 at() 方法来访问和修改元素,只能通过迭代器来完成。

此外,由于 std::list 的迭代器不支持随机访问,因此不能使用 [] 运算符来访问元素。

其它

除了上述操作,list 还支持以下操作:

  • size():返回 list 中元素的个数。
  • empty():判断 list 是否为空。
  • clear():清空 list 中的元素。
  • sort():将 list 中的元素进行排序。

queue

std::queue 是 STL 中的队列容器,它可以用来存储一系列具有相同数据类型的元素,并支持队列的基本操作,如入队、出队、获取队首元素等。下面是 std::queue 的常用用法

创建

std::queue<int> q;  // 创建一个空队列,元素类型为 int

增/删

q.push(2); //插入元素1到队列尾部
q.pop();  // 从队列头部弹出元素

改(X)/查(√)

可以使用 front() 成员函数来获取队列的头部元素,但是需要注意,在调用该函数之前必须先判断队列是否为空

// 获取队列的头部元素
if (!q.empty()) {
    cout << "Front element: " << q.front() << endl;
}

不支持直接修改队列内部元素,也不支持直接获取尾部元素

其它

q.empty();  // 判断是否队列为空
q.size();   // 获取队列内元素个数

stack

std::stack 是 C++ 标准库中的一个容器适配器,它提供了一个 LIFO(后进先出)的数据结构。std::stack 支持以下基本操作:

创建

#include <stack>
stack<int> s; // 创建栈s

增删

s.push(1);  // 元素1从栈顶入栈
s.pop();	// 弹出出栈顶元素

改(X)/查(√)

s.top();  // 获取栈顶元素

不支持修改栈内元素

其它

s.size(); // 获取栈内元素个数
s.empty(); // 判断栈是否为空。

map

C++ 中的 map 是一种关联容器(associative container),用于存储键值对。在 map 中,每个键唯一且与一个值相关联。

map底层是红黑树,是有序的

以下是一些常用的 map 操作

创建

#include <map>

std::map<std::string, int> myMap;  // 创建一个空 map,键类型为 string,值类型为 int

// 创建并初始化一个 map
std::map<std::string, int> myMap2 = {{"apple", 1}, {"banana", 2}, {"orange", 3}};

增删

myMap["key"] = value;  // 插入键值对
myMap.insert(key, value)
myMap.erase(key);  // 删除键为 key 的元素
myMap.clear();  // 删除所有元素

改/查

myMap["key"] = value;  // 改(已经存在key的时候是修改)
int value = myMap["key"];  // 访问键对应的值

// 检查是否存在某个键
if (myMap.find("key") != myMap.end()) {
  // 执行操作
}

迭代器

// 使用迭代器遍历 map
for (auto it = myMap.begin(); it != myMap.end(); ++it) {
  std::cout << it->first << " => " << it->second << '\n';
}

// 使用范围遍历语句遍历 map
for (const auto& [key, value] : myMap) {
  std::cout << key << " => " << value << '\n';
}

其他

count(key) 判断是否存在键为key的元素,存在返回1,否则返回0

std::map<std::string, int> myMap = {{"apple", 1}, {"banana", 2}, {"orange", 3}};

if (myMap.count("apple")) {
  std::cout << "apple exists in myMap.\n";
} else {
  std::cout << "apple does not exist in myMap.\n";
}
empty(); //是否为空
size();  // 键值对个数

find(key) 函数用于查找键为 key 的元素,如果找到了,则返回一个指向该元素的迭代器,否则返回 map 的尾部迭代器

std::map<std::string, int> myMap = {{"apple", 1}, {"banana", 2}, {"orange", 3}};

auto it = myMap.find("apple");
if (it != myMap.end()) {
  std::cout << "apple found in myMap with value " << it->second << '\n';
} else {
  std::cout << "apple not found in myMap.\n";
}

unordered_map

C++ 中的 unordered_map 是一种关联容器(associative container),与 map 类似,也用于存储键值对。

不同之处在于,unordered_map 不保证元素的顺序,并使用哈希表来实现快速查找。

unordered_map 一些操作与map基本相同

需要注意的是,unordered_map 的查询操作通常比 map 更快,但存储的元素顺序是不确定的。因此,当需要对元素进行有序访问时,应该使用 map

创建

#include <unordered_map>

std::unordered_map<std::string, int> myMap;  // 创建一个空 unordered_map,键类型为 string,值类型为 int

// 创建并初始化一个 unordered_map
std::unordered_map<std::string, int> myMap2 = {{"apple", 1}, {"banana", 2}, {"orange", 3}};

增删

myMap["key"] = value;  // 插入键值对

myMap.erase(key);  // 删除键为 key 的元素
myMap.clear();  // 删除所有元素

改/查

myMap["key"] = value;  // 修改键key的值
int value = myMap["key"];  // 访问键对应的值

// 检查是否存在某个键
if (myMap.find("key") != myMap.end()) {
  // 执行操作
}

迭代器

// 使用迭代器遍历 unordered_map
for (auto it = myMap.begin(); it != myMap.end(); ++it) {
  std::cout << it->first << " => " << it->second << '\n';
}

// 使用范围遍历语句遍历 unordered_map
for (const auto& [key, value] : myMap) {
  std::cout << key << " => " << value << '\n';
}
posted @ 2023-03-14 21:17  aJream  阅读(25)  评论(0编辑  收藏  举报