首页 分享 c++容器说明和基本使用方法(最全/全部内容)

c++容器说明和基本使用方法(最全/全部内容)

来源:花匠小妙招 时间:2024-12-19 12:52

c++容器基本使用方法

顺序性容器

类型特性vector可变大小数组。支持快速随机访问。在尾部之外的位置插入或删除元素可能很慢deque双端队列。支持快速随机访问。在头尾位置插入或删除速度很快list双向链表。只支持双向顺序访问。在任何位置插入或删除速度都很快forward_list单向链表。只支持单向顺序访问。在任何位置插入或删除速度都很快array固定大小数组。支持快速随机访问。不能添加或删除元素string类似vector,但用于保存字符。支持快速随机访问。在尾部插入或删除速度很快

forward_list和array是C++11新增类型。与内置数组相比,array更安全易用。forward_list没有size操作。

容器选择原则:

除非有合适的理由选择其他容器,否则应该使用vector。如果程序有很多小的元素,且空间的额外开销很重要,则不要使用list或forward_list。如果程序要求随机访问容器元素,则应该使用vector或deque。如果程序需要在容器头尾位置插入/删除元素,但不会在中间位置操作,则应该使用deque。如果程序只有在读取输入时才需要在容器中间位置插入元素,之后需要随机访问元素。则: 先确定是否真的需要在容器中间位置插入元素。当处理输入数据时,可以先向vector追加数据,再调用标准库的sort函数重排元素,从而避免在中间位置添加元素。如果必须在中间位置插入元素,可以在输入阶段使用list。输入完成后将list中的内容拷贝到vector中。 不确定应该使用哪种容器时,可以先只使用vector和list的公共操作:使用迭代器,不使用下标操作,避免随机访问。这样在必要时选择vector或list都很方便。 vector

可以理解vector是一个长度可变的数组。数组它在一创建之后就是确定好的大小,并且存放在静态空间,但是vector它内部空间大小可变动的。

1. 头文件

#include <vector> 1 2. 常用的API 构造函数

//1.默认构造,无参构造 vector<int> v1; for (int i = 0; i < 10; ++i) {v1.push_back(i); } // 2.利用区间方式构造 vector<int> v2(v1.begin(), v1.end()); 1234567 赋值操作

//直接赋值 vector<int> v2; v2 = v1; //assign赋值 vector<int> v3; v3.assign(v1.begin(), v1.end()); 12345678 插入和删除

vector<int> v1; //尾部插入 v1.push_back(1); v1.push_back(2); v1.push_back(3); v1.push_back(4); v1.push_back(5); // 尾部删除 v1.pop_back(); //在v1的头部插入-1元素 v1.insert(v1.begin(), -1); //在v1的头部插入两个值为520的元素 v1.insert(v1.begin(), 2, 520); //删除头部第一个元素 v1.erase(v1.begin()); //清空所有的元素 // 方法1 v1.erase(v1.begin(), v.end()); // 方法2 v1.clear();

1234567891011121314151617181920212223242526 容量和大小

size() 函数返回容器当前所包含的元素数量,而 capacity() 函数返回容器在不重新分配内存的情况下可以容纳的元素数量。

// 判断容器是否为空, 如果为空返回true,否则返回false v1.empty(); // 获取容器的容量 v1.capacity(); // 获取容器的大小 //(注意!这里的容器的大小可以理解为里面存储的元素的个数) v1.size(); // 修改容器的容量 v1.resize(100) // 扩容到可容纳100个元素 v1.resize(10, 100) //将向量 v1 调整为包含 10 个元素的大小,并用值为 100 的元素填充向量。 12345678910111213 数据访问

// 下标访问(Subscript Access):使用下标操作符 [] 来访问指定位置的元素 vector<int> vec = {1, 2, 3, 4, 5}; int value = vec[2]; // 获取索引为 2 的元素,即第三个元素,value 等于 3 //迭代器访问(Iterator Access):使用迭代器来遍历 vector 中的元素 for (auto it = vec.begin(); it != vec.end(); ++it) { cout << *it << " "; // 输出每个元素的值 } // 范围循环(Range-based Loop):使用 C++11 引入的范围循环来遍历 vector 中的元素。 for (int value : vec) { cout << value << " "; // 输出每个元素的值 } //at() 函数:使用 at() 函数来访问指定位置的元素,可以在访问越界时抛出 out_of_range 异常。 int value = vec.at(2); // 获取索引为 2 的元素,即第三个元素,value 等于 3 // front() 和 back() 函数:分别用于访问 vector 的第一个和最后一个元素 int first = vec.front(); // 获取第一个元素,即 1 int last = vec.back(); // 获取最后一个元素,即 5

12345678910111213141516171819202122 deque 1.头文件

#include <deque> 1 2.常用API 构造函数

// 创建一个空的 deque 对象 d1 deque<int> d1; d1.push_back(1); d1.push_back(2); d1.push_back(3); // 使用 d1 的内容初始化另一个 deque d2,即 d2 包含了 d1 的所有元素 deque<int> d2(d1); // 创建一个包含 10 个元素且每个元素的值都为 100 的 deque 对象 d3 deque<int> d3(10, 100); deque<int> d4; d4 = d3; // // 将 d3 的内容复制给 d4,即 d4 现在包含了 d3 的所有元素

12345678910111213141516 赋值操作

deque<int> d1; d1.push_back(1); d1.push_back(2); d1.push_back(3); deque<int> d2; d2 = d1; // 直接赋值 //使用assign deque<int> d3; d3.assign(d1.begin, d1.end()); //将d1中[beg, end)区间中的数据拷贝赋值给d3 deque<int> d4; d4.assign(10, 100); // 添加10个值为100的元素

12345678910111213141516 大小和容量

这里的容量和大小同vector一样,不理解直接看vector中的解释

// 获取容量 d1.capacity(); //获取大小 d2.size(); //改变容量大小 d1.resize(10); 123456789 插入和删除

deque<int> d; //尾插 d.push_back(1); d.push_back(2); //头插 d.push_front(-1); d.push_front(-2); d.insert(d.begin(), -3); print(d) // -3,-2,-1,1,2 //尾部删除 d.pop_back(); //头部删除 d.pop_front(); print(d); //-2,-1,1 deque<int>::iterator it = d.begin(); d.erase(it); //删除开头的第一个元素 //清空所有元素 // 1.方法一 d.erase(d.begin(),d.end()); // 2.方法二 d.clear();

12345678910111213141516171819202122232425 数据访问

// 下标访问(Subscript Access):使用下标操作符 [] 来访问指定位置的元素。 // deque 支持随机访问,因此可以像访问数组一样使用下标来访问元素。 deque<int> dq = {1, 2, 3, 4, 5}; int value = dq[2]; // 获取索引为 2 的元素,即第三个元素,value 等于 3 // 迭代器访问(Iterator Access):使用迭代器来遍历 deque 中的元素。 // 可以使用 begin() 和 end() 函数来获取迭代器的起始位置和结束位置。 for (auto it = dq.begin(); it != dq.end(); ++it) { cout << *it << " "; // 输出每个元素的值 } // 范围循环(Range-based Loop):使用 C++11 引入的范围循环来遍历 deque 中的元素。 for (int value : dq) { cout << value << " "; // 输出每个元素的值 } // at() 函数:使用 at() 函数来访问指定位置的元素,可以在访问越界时抛出 out_of_range 异常。 int value = dq.at(2); // 获取索引为 2 的元素,即第三个元素,value 等于 3 // front() 和 back() 函数:分别用于访问 deque 的第一个和最后一个元素。 int first = dq.front(); // 获取第一个元素,即 1 int last = dq.back(); // 获取最后一个元素,即 5

1234567891011121314151617181920212223 list 1.头文件

#include <list> 1 2.常用API 构造函数

int arr[] = {1, 2, 3, 4, 5}; // 从数组 arr 的开头到第 4 个元素(不包括第 4 个元素)构造 list list<int> myList1(arr, arr + 3); // 构造一个包含 5 个元素且每个元素的值都是 100 的 list list<int> myList2(5, 100); 123456 赋值操作

// assign(beg, end) int arr[] = {1, 2, 3, 4, 5}; list<int> myList1; myList1.assign(arr, arr + 3); // 将数组 arr 的前三个元素赋值给 myList1 list<int> myList2; myList2.assign(5, 100); // 将 5 个元素值为 100 赋值给 myList2 list<int> myList = {1, 2, 3}; list<int> myList3 = {4, 5, 6}; myList.swap(myList3); // 交换 myList 和 myList3 的元素 1234567891011 插入和删除操作

list<int> myList; // push_back(elem) myList.push_back(1); // 在容器尾部加入一个元素 // push_front(elem) myList.push_front(0); // 在容器开头插入一个元素 // insert(pos, elem) auto it = myList.begin(); ++it; myList.insert(it, 2); // 在 pos 位置插入 elem 元素的拷贝 // insert(pos, n, elem) myList.insert(myList.begin(), 3, 3); // 在 pos 位置插入 n 个 elem 数据 // insert(pos, beg, end) int arr[] = {4, 5, 6}; myList.insert(myList.end(), begin(arr), end(arr)); // 在 pos 位置插入 [beg, end) 区间的数据 // 输出容器中的元素 for (auto& elem : myList) { cout << elem << " "; } cout << endl; // pop_back() myList.pop_back(); // 删除容器中最后一个元素 // pop_front() myList.pop_front(); // 从容器开头移除第一个元素 // erase(pos) myList.erase(myList.begin()); // 删除 pos 位置的数据 // erase(beg, end) auto eraseBegin = myList.begin(); auto eraseEnd = myList.begin(); advance(eraseBegin, 1); advance(eraseEnd, 3); myList.erase(eraseBegin, eraseEnd); // 删除 [beg, end) 区间的数据 // remove(elem) myList.push_back(6); myList.push_back(6); myList.push_back(6); myList.remove(6); // 删除容器中所有与 elem 值匹配的元素 // clear() myList.clear(); // 移除容器的所有数据

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152 数据访问

对于 list,数据访问的主要方式是通过迭代器进行遍历访问,因为 list 不支持随机访问。

// 迭代器访问(Iterator Access):使用迭代器来遍历 list 中的元素。 list<int> myList = {1, 2, 3, 4, 5}; for (auto it = myList.begin(); it != myList.end(); ++it) { cout << *it << " "; // 输出每个元素的值 } //范围循环(Range-based Loop):使用 C++11 引入的范围循环来遍历 list 中的元素。 for (int value : myList) { cout << value << " "; // 输出每个元素的值 } //front() 和 back() 函数:分别用于访问 list 的第一个和最后一个元素 int first = myList.front(); // 获取第一个元素,即 1 int last = myList.back(); // 获取最后一个元素,即 5 //at() 函数:由于 list 不支持随机访问,因此不能像数组或向量一样使用下标操作符 []。但是可以使用 at() 函数来访问指定位置的元素。 int value = next(myList.begin(), 2); // 获取索引为 2 的元素,即第三个元素,value 等于 3

12345678910111213141516 forword_list

单向链表是一种线性数据结构,其中的每个元素(节点)都包含一个指向下一个元素的指针。与双向链表相比,单向链表中的节点只保存了指向下一个节点的指针,而不保存指向前一个节点的指针。这使得单向链表在内存使用上更加高效,但在某些操作(如反向遍历)上可能效率较低。

1.头文件

#include <forward_list> 1 2.常用API

forward_list<int> myForwardList = {3, 1, 4, 1, 5, 9}; // begin() 和 end() cout << "Elements in the forward_list: "; for (auto it = myForwardList.begin(); it != myForwardList.end(); ++it) { cout << *it << " "; } cout << endl; // assign() myForwardList.assign({2, 7, 1}); cout << "After assign(), elements in the forward_list: "; for (auto& elem : myForwardList) { cout << elem << " "; } cout << endl; // push_front() myForwardList.push_front(8); cout << "After push_front(), elements in the forward_list: "; for (auto& elem : myForwardList) { cout << elem << " "; } cout << endl; // pop_front() myForwardList.pop_front(); cout << "After pop_front(), elements in the forward_list: "; for (auto& elem : myForwardList) { cout << elem << " "; } cout << endl; // swap() forward_list<int> anotherForwardList = {6, 5, 4}; myForwardList.swap(anotherForwardList); cout << "After swap(), elements in the forward_list: "; for (auto& elem : myForwardList) { cout << elem << " "; } cout << endl; // remove(val) myForwardList.remove(5); cout << "After remove(5), elements in the forward_list: "; for (auto& elem : myForwardList) { cout << elem << " "; } cout << endl; // sort() myForwardList.sort(); cout << "After sort(), elements in the forward_list: "; for (auto& elem : myForwardList) { cout << elem << " "; } cout << endl;

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657

关联式容器

关联容器支持高效的关键字查找和访问操作。2个主要的关联容器(associative-container)类型是map和set。

map中的元素是一些键值对(key-value):关键字起索引作用,值表示与索引相关联的数据。set中每个元素只包含一个关键字,支持高效的关键字查询操作:检查一个给定关键字是否在set中。

标准库提供了8个关联容器,它们之间的不同体现在三个方面:

是map还是set类型。是否允许保存重复的关键字。是否按顺序保存元素。

允许重复保存关键字的容器名字都包含单词multi;无序保存元素的容器名字都以单词unordered开头。

有序容器:

类型特性map保存键值对的关联数组set只保存关键字的容器multimap关键字可重复出现的mapmultiset关键字可重复出现的set

无序容器:

类型特性unordered_map用哈希函数管理的mapunordered_set用哈希函数管理的setunordered_multimap关键字可重复出现的unordered_mapunordered_multiset关键字可重复出现的unordered_set

map和multimap类型定义在头文件map中;set和multiset类型定义在头文件set中;无序容器定义在头文件unordered_map和unordered_set中。

选择建议

如果需要有序存储并且对性能要求不是特别高,可以选择 map 或 set。
如果对元素的存储顺序没有特殊要求,而且希望在插入、查找、删除操作中获得更好的性能,可以选择unordered_map 或 unordered_set。

map和multimap 1.头文件

#include <map> 1 2.共同特征 构造函数 默认构造函数:构造一个空容器。范围构造函数:接受两个迭代器,用于指定范围的元素,以初始化容器。复制构造函数:从另一个相同类型的容器复制元素。 赋值操作符 operator=:将另一个容器的内容赋值给当前容器。 迭代器 begin():返回指向容器中第一个元素的迭代器。end():返回指向容器最后一个元素之后位置的迭代器。cbegin():返回指向容器中第一个元素的 const 迭代器。cend():返回指向容器最后一个元素之后位置的 const 迭代器。 容量 empty():检查容器是否为空。size():返回容器中元素的数量。max_size():返回容器可能包含的最大元素数量。 3.map 特有 插入: insert(pair_type&&):插入键值对,如果键已存在,则不插入。insert(const value_type&):插入键值对,如果键已存在,则不插入。emplace(Args&&...):用给定参数构造元素并插入容器,如果键已存在,则不插入。 访问元素: operator[]:访问给定键对应的值,如果键不存在,则插入键并返回默认值。at(const Key&):访问给定键对应的值,如果键不存在,则抛出异常。find(const Key&):查找给定键对应的迭代器,如果找到,则返回指向该元素的迭代器;否则返回 end()。 删除元素: erase(const Key&):删除指定键对应的元素。clear():清空容器。 4. multimap 特有 插入: insert(pair_type&&):插入键值对,允许键重复。insert(const value_type&):插入键值对,允许键重复。emplace(Args&&...):用给定参数构造元素并插入容器,允许键重复。 访问元素: find(const Key&):查找给定键对应的迭代器,如果找到,则返回指向第一个匹配元素的迭代器;否则返回 end()。count(const Key&):返回给定键的数量。 删除元素: erase(const Key&):删除所有与指定键匹配的元素。 其他: equal_range(const Key&):返回一个 pair,其 first 成员是指向第一个具有给定键的元素的迭代器,而 second 成员是指向最后一个具有给定键的元素之后位置的迭代器。

// 使用 map map<int, string> myMap; // 插入元素 //insert 方法可能会创建临时对象,并进行拷贝或者移动操作, // 而 emplace 方法直接在容器中就地构造元素,避免了额外的拷贝或移动操作,因此在性能上可能更高效 myMap.insert({1, "One"}); myMap.emplace(2, "Two"); myMap[3] = "Three"; // 访问元素 cout << "Value at key 2: " << myMap.at(2) << endl; // 查找元素 auto it = myMap.find(3); if (it != myMap.end()) { cout << "Found key 3: " << it->second << endl; } // 删除元素 myMap.erase(1); // 遍历元素 for (const auto& pair : myMap) { cout << "Key: " << pair.first << ", Value: " << pair.second << endl; } // 使用 multimap multimap<int, string> myMultiMap; // 插入元素 myMultiMap.emplace(1, "Apple"); myMultiMap.emplace(2, "Banana"); myMultiMap.emplace(2, "Orange"); // 访问元素 cout << "Number of values with key 2: " << myMultiMap.count(2) << endl; // 删除元素 myMultiMap.erase(2); // 删除所有键为2的元素 // 遍历元素 for (const auto& pair : myMultiMap) { cout << "Key: " << pair.first << ", Value: " << pair.second << endl; } // 获取键为 2 的所有值 auto range = myMultiMap.equal_range(2); for (auto it = range.first; it != range.second; ++it) { cout << "Value: " << it->second << endl; }

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152

set 和 multiset 是 C++ 标准库提供的关联式容器,它们用于存储一组唯一值和一组允许重复值的集合。下面是它们的 API 的详细说明:

set和multiset 1.头文件

#include <set> 1 2.共同特征 构造函数 默认构造函数:构造一个空容器。范围构造函数:接受两个迭代器,用于指定范围的元素,以初始化容器。复制构造函数:从另一个相同类型的容器复制元素。 赋值操作符: operator=:将另一个容器的内容赋值给当前容器。 迭代器 begin():返回指向容器中第一个元素的迭代器。end():返回指向容器最后一个元素之后位置的迭代器。cbegin():返回指向容器中第一个元素的 const 迭代器。cend():返回指向容器最后一个元素之后位置的 const 迭代器。

容量

empty():检查容器是否为空。size():返回容器中元素的数量。max_size():返回容器可能包含的最大元素数量。 3.set 特有 插入 insert(const value_type&):插入单个元素,如果元素已存在,则不插入。emplace(Args&&...):用给定参数构造元素并插入容器,如果元素已存在,则不插入。 访问元素 find(const Key&):查找给定键对应的迭代器,如果找到,则返回指向该元素的迭代器;否则返回 end()。 删除元素 erase(const Key&):删除指定键对应的元素。clear():清空容器。 4.multiset 特有

插入

insert(const value_type&):插入单个元素,允许重复元素的存在。emplace(Args&&...):用给定参数构造元素并插入容器,允许重复元素的存在。 访问元素 find(const Key&):查找给定键对应的迭代器,如果找到,则返回指向第一个匹配元素的迭代器;否则返回 end()。count(const Key&):返回给定键的数量。 删除元素 erase(const Key&):删除所有与指定键匹配的元素。 其他 equal_range(const Key&):返回一个 pair,其 first 成员是指向第一个具有给定键的元素的迭代器,而 second 成员是指向最后一个具有给定键的元素之后位置的迭代器。

// 使用 set set<int> mySet; // 插入元素 mySet.insert(1); mySet.insert(2); mySet.insert(3); // 插入重复元素 mySet.insert(2); // 这个不会插入,因为元素已经存在 // 遍历元素 cout << "Elements in set:" << endl; for (const auto& elem : mySet) { cout << elem << endl; } // 检查元素是否存在 int key = 2; auto it = mySet.find(key); if (it != mySet.end()) { cout << "Element " << key << " found in set" << endl; } else { cout << "Element " << key << " not found in set" << endl; } // 删除元素 mySet.erase(3); // 删除元素3 // 使用 multiset multiset<int> myMultiSet; // 插入元素 myMultiSet.insert(1); myMultiSet.insert(2); myMultiSet.insert(2); // 插入重复元素 // 遍历元素 cout << "Elements in multiset:" << endl; for (const auto& elem : myMultiSet) { cout << elem << endl; } // 计算特定元素的数量 int key2 = 2; int count = myMultiSet.count(key2); cout << "Number of " << key2 << " in multiset: " << count << endl;

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647 unordered_map和unordered_set 1.map与unordered_map区别

map 是一个关联式容器,用于存储键值对。它基于红黑树实现,保持元素的有序性。

插入、查找、删除操作的平均时间复杂度为 O(log n)。

元素按照键的大小顺序进行排序。

unordered_map 是一个关联式容器,用于存储键值对。它基于哈希表实现,无序存储元素。

插入、查找、删除操作的平均时间复杂度为 O(1),在理想情况下是常数时间。

2.set与unordered_set区别

set 是一个关联式容器,用于存储一组唯一值的集合。它基于红黑树实现,保持元素的有序性。

插入、查找、删除操作的平均时间复杂度为 O(log n)。

元素按照大小顺序进行排序。

unordered_set 是一个关联式容器,用于存储一组唯一值的集合。它基于哈希表实现,无序存储元素。

插入、查找、删除操作的平均时间复杂度为 O(1),在理想情况下是常数时间。

3.常用API

和map与set的使用是一样。

// 使用 unordered_map unordered_map<int, string> myUnorderedMap; // 插入元素 myUnorderedMap.insert({1, "One"}); myUnorderedMap.emplace(2, "Two"); myUnorderedMap[3] = "Three"; // 访问元素 cout << "Value at key 2: " << myUnorderedMap.at(2) << endl; // 查找元素 auto it = myUnorderedMap.find(3); if (it != myUnorderedMap.end()) { cout << "Found key 3: " << it->second << endl; } // 删除元素 myUnorderedMap.erase(1); // 遍历元素 for (const auto& pair : myUnorderedMap) { cout << "Key: " << pair.first << ", Value: " << pair.second << endl; } // 使用 unordered_set unordered_set<int> myUnorderedSet; // 插入元素 myUnorderedSet.insert(1); myUnorderedSet.insert(2); myUnorderedSet.insert(3); // 查找元素 int key = 2; auto setIt = myUnorderedSet.find(key); if (setIt != myUnorderedSet.end()) { cout << "Found element " << key << " in set" << endl; } // 删除元素 myUnorderedSet.erase(3); // 遍历元素 for (const auto& elem : myUnorderedSet) { cout << "Element: " << elem << endl; }

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647

相关知识

无限暖暖兑换码在哪里使用 无限暖暖兑换码在哪里及使用方法说明
常见C/C++ XML解析器比较
C++做的玫瑰花
氮磷钾和微量元素肥的使用方法!最全面的知识!
探索C++之美:玫瑰花代码项目推荐
水溶肥的使用方法和注意事项
字符串 (C++/CX)
史上最全的养花妙招有哪些
史上最全家庭种菜攻略
最全草莓虫害防治说明

网址: c++容器说明和基本使用方法(最全/全部内容) https://www.huajiangbk.com/newsview1184050.html

所属分类:花卉
上一篇: C++标准库list详解与示例
下一篇: 容器花箱在移动式绿化中的运用

推荐分享