c++ STL–容器 (第二部分)
1.vector向量(序列性容器)
1.特点:
数据的存储访问比较方便,可以像数组一阿姨那个使用[index]访问或修改值,适用于对元素修改和查看比较多的情况,对于insert或erase比较多的操作,很影响效率,不建议使用vector
2.使用的头文件为
#include <vector>
using namespace std;//需要打开std命名空间
3.关于vector容器一些功能的使用
我们用模版T实例化为int类型的vector来进行功能的测试
1.创建vector
vector<int> vec;//空的向量
vector<int> vec2(2);//构建了容量和使用量,并使用默认的初始化值,这里容量和使用量都是2
vector<int> vec3(2,3);//构建了容量和使用量,并指定了初始化值,这里容量和使用量都是2,初始值为3
vector<int> vec4{ 1,2,3,4 };//使用初始化列表,进行构建 这里容量和使用量都是4int arr[5] = { 5,6,7,8,9 };//通过连续的空间(比如数组)进行构建向量
vector<int> vec5(arr, arr + 3);//左闭右开
2.容量,使用量
cout << vec2.capacity() << " " << vec2.size() << endl;//输出容量 使用量
3.遍历
1.迭代器遍历
vector<int>::iterator ite = vec4.begin();while (ite != vec4.end()) {cout << *ite << " ";ite++;}cout << endl;
2.范围遍历
for (int v : vec5) cout << v << " ";
4.vector的尾添加和尾删除
注意:当容量不够时,容量是以1.5倍扩容
vec5.push_back(7);//尾添加
vec5.pop_back();//尾删除
5.vector的插入和删除
注意:当容量不够时,容量是以1.5倍扩容
ite = vec5.begin();
vec5.insert(ite, 4);//在指向位置之前添加ite += 2;//此迭代器支持+=
ite=vec5.erase(ite);//删除时,迭代器会失效,可以接一下返回值,返回的是删除的下一个的迭代器
5.vector的清空
vec.clear();// //使用量为0,容量不变,相当于是把矿泉水倒没了,瓶子还在
6.重新设定一个使用量
vec.resize(3);//重新设定使用量,如果新设定的使用量小于容量,那么容量不会受影响,如果超过了容量,会导致扩容
7.交换两个向量
vec.swap(vec2);//可以用此方法来清空向量(容量和使用量均为0)
vector<int>().swap(vec);//这里是把已存在的向量和创建的临时变量(使用量和容量均为0)进行交换
8.将容量缩小到和使用量大小一样
vec3.shrink_to_fit();
2.list与vector的对比
1.vector是连续性空间,顺序存储,list链式结构体,链式存储
2.vector在非尾部插入,删除节点会导致其他元素的拷贝移动,list则不会影响其他节点元素
3.vector一次性分配好内存,使用量不够时,申请内存重新分配。list每次插入新节点时都会申请内存
4.vector随机访问性能好,插入删除性能差;list随机访问性能差,插入删除性能好
5.vector具有容量和使用量的概念,而list只有使用量(即长度)概念
3.deque双端队列(序列性容器)
1.特点:
deque是一种双向开口的连续性空间,可以在头尾两端分别做元素的插入和删除操作-
2.使用的头文件为
#include <deque>
using namespace std;//需要打开std命名空间
3.关于deque容器一些功能的使用
我们用模版T实例化为int类型的deque来进行功能的测试
1.创建deque
deque<int> de{ 1,2,3,4 };//使用初始化列表
2.头添加,尾添加,获取长度
de.push_front(0);//头添加
de.push_back(5);//尾添加
cout << de.size() << endl;//输出长度
3.遍历
1.迭代器
deque<int>::iterator ite = de.begin();
while (ite != de.end()) {cout << *ite << " ";ite+=1;
}
2.范围遍历
for (int v : de) {cout << v << " ";
}
4.通过下标访问元素
for (int i = 0; i < de.size(); i += 1) {cout << de[i] << " ";//通过下标访问元素
}
4.map映射表(关联性容器)
1.特点
所有元素都会根据元素的键值自动排序,map的所有元素都是pair,同时拥有键值和实值。不允许两个元素拥有相同的键值,map的键值关系到map元素的排列规则,任意改变map元素键值将严重破环map的组织,所以不可以通过map的迭代器来改变map的键值,但是可以通过迭代器来改变元素的实值
查找效率:O(log2(n)),内部实现红黑树
2.使用的头文件为
#include <map>
using namespace std;//需要打开std命名空间
3.关于map容器一些功能的使用
我们用模版T实例化为(char,int)类型的map来进行功能的测试
1.创建map
map<char, int> m1{ {'r',1},{'q',2}};//使用初始化列表
m1['a'] = 3;//[]里是键值,=右边的是实值
2.遍历
1.迭代器
map<char, int>::iterator ite = m1.begin();
while (ite != m1.end()) {cout << ite->first << "-" << ite->second << endl;ite++;
}
2.范围遍历
for (pair<char, int> v : m1) {cout << v.first << "-" << v.second<<" ";
}
3.元素的插入
m1.insert(pair<char, int>('b', 4));
//如果键值存在,则插入失败,可通过bool判断,返回的迭代器指向的是原有键值的元素//此函数的返回值为pair<迭代器,bool>,我们接一下,看一下它的bool返回值
pair<map<char, int>::iterator, bool> pr = m1.insert(pair<char, int>('b', 5));
cout << "bool =" << pr.second << endl;//bool = 0
cout << pr.first->first << "-" << pr.first->second << endl;//返回的迭代器指向的是原有键值的元素
4.元素的删除
ite = m1.begin();
ite = m1.erase(ite);//可以用迭代器接一下返回值,防止迭代器失效
5.元素的查找
ite = m1.find('r');//通过键值找,没找到返回的是无效的那个元素( m1.end() )
6.upper_bound(返回大于某键值的map的迭代器),lower_bound(返回大于等于某键值的map的迭代器)
ite = m1.upper_bound('c');//返回大于该键值的map的迭代器
ite = m1.lower_bound('c');//返回大于等于该键值的map的迭代器//可以根据这种方法判断键值是否存在
char c = 'i';
if (m1.upper_bound(c) != m1.lower_bound(c)) {cout << "键值存在" << endl;
}
else {cout << "键值不存在" << endl;
}
5.set集合(关联性容器)
1.特点
所有元素都会根据元素的键值自动排序,set的元素不像map那样可以同时拥有键值和实值,set元素的键值就是实值,实值就是键值,不允许两个元素拥有相同的键值,因为set的元素值就是其键值,关系到set元素的排列规则,任意改变set元素值将严重破环set的组织
查找效率O(log2(n)),内部实现红黑树
2.使用的头文件为
#include <unordered_map>
using namespace std;//需要打开std命名空间
3.关于set容器一些功能的使用
我们用模版T实例化为int类型的set来进行功能的测试
1.创建set
set<int> st{4,2,6,0};//使用初始化列表
2.遍历
1.迭代器
set<int> ::iterator ite = st.begin();
while (ite != st.end()) {cout << *ite<< endl;ite++;
}
2.范围遍历
for (int v : m1) {cout << v <<" ";
}
3.set的插入
st.insert(4);
//如果键值存在,则插入失败,可通过bool判断,返回的迭代器指向的是原有键值的元素
4.set的删除
ite = st.begin();
ite = st.erase(ite);//可以用迭代器接一下返回值,防止迭代器失效
5.hash_map哈希表(关联性容器)
1.特点
基于hashTable(哈希表),数据的存储和查找效率非常高,几乎可以看作常量时间,相应的代价是消耗更多的内存,使用一个较大的数组来存储空间,经过计算,使得每个元素与数组下标有唯一的对应关系,查找时直接定位
查找效率O(1)
无序
2.使用的头文件为
#include <unordered_map>
using namespace std;//需要打开std命名空间
3.关于hash_map容器一些功能的使用
我们用模版T实例化为(char,int)类型的hash_map来进行功能的测试
1.创建hash_map
unorder_map<char, int> m1{ {'r',1},{'q',2}};//使用初始化列表
m1['a'] = 3;//[]里是键值,=右边的是实值
2.遍历
1.迭代器
unorder_map<char, int>::iterator ite = m1.begin();
while (ite != m1.end()) {cout << ite->first << "-" << ite->second << endl;ite++;
}
2.范围遍历
for (pair<char, int> v : m1) {cout << v.first << "-" << v.second<<" ";
}
3.元素的插入
m1.insert(pair<char, int>('b', 4));
//如果键值存在,则插入失败,可通过bool判断,返回的迭代器指向的是原有键值的元素
4.元素的删除
ite = m1.begin();
ite = m1.erase(ite);//可以用迭代器接一下返回值,防止迭代器失效
5.元素的查找
ite = m1.find('r');//通过键值找,没找到返回的是无效的那个元素( m1.end() )