c++ STL--容器 (第二部分)

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 };//使用初始化列表,进行构建 这里容量和使用量都是4

int 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() )

猜你喜欢

转载自blog.csdn.net/m0_73483024/article/details/132241010