学习C++ STL (二) 几种容器详解

文章详细介绍了C++标准模板库(STL)中的几种重要容器:vector的功能、动态拓展、迭代器、构造函数、赋值操作、容量和大小、插入和删除、数据存取以及互换容器;deque的特性、与vector的区别、内部工作原理、构造函数、赋值操作和大小操作;stack的基本概念、操作以及与队列的区别;queue的概念和操作;以及list的链表特性、构造函数、赋值和交换、大小操作、插入删除以及反转和排序。
摘要由CSDN通过智能技术生成

vector容器

功能:

vector和数组十分相似,也称为单端数组。不同之处在于数组是静态孔空间,vector可以动态拓展。

动态拓展:

不是在原空间的基础上拓展新的空间,而是找更大的空间,然后将原数据拷贝到新的空间,释放掉原空间。

vector迭代器

vector的迭代器是支持随机访问的迭代器

构造函数

  • 无参构造
  • 可以用一个vector对象的某个区间的内容初始化
  • 用另一个vector对象初始化
  • 使用n个相同元素初始化
void test09()
{
	vector<int >v; // 无参构造
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	vector<int> v1(v.begin(), v.end()); //用一个vector对象区间的内容赋值
	vector<int> v2(v1);              //使用另一个vector对象初始化
	vector<int> v3(5, 15);           //使用5个15初始化vector

	//输出数据
	for (vector<int>::iterator h = v.begin(); h != v.end(); h++)
	{
		cout << *h << ' ';
	}
	cout << endl;
	for (vector<int>::iterator h = v1.begin(); h != v1.end(); h++)
	{
		cout << *h << ' ';
	}
	cout << endl;
	for (vector<int>::iterator h = v2.begin(); h != v2.end(); h++)
	{
		cout << *h << ' ';
	}
	cout << endl;
	for (vector<int>::iterator h = v3.begin(); h != v3.end(); h++)
	{
		cout << *h << ' ';
	}
	cout << endl;
}
int main()
{
	//test01();
	//test03();
	//test04();
	//test05();
	//test06();
	//test07();
	//test08();
	test09();
}

赋值操作

  • =’赋值
  • assign 赋值(2种方式)
//vector赋值操作
void test10()
{
	//等号赋值
	vector<int> v1;
	for(int i = 0;i < 5;i++)
	{
		v1.push_back(i);
	}

	vector<int> v2;
	v2 = v1;   //等号赋值操作
	//迭代器输出数据
	for (vector<int >::iterator v = v2.begin(); v != v2.end(); v++)
	{
		cout << *v << ' ';
	}
	cout << endl << "________________________________" << endl << "assign 赋值操作 " << endl;

	//assign赋值
	vector<int >v3;
	v3.assign(v2.begin(),v2.end());  //assign 赋值操作
	//迭代器输出数据
	for (vector<int >::iterator v = v3.begin(); v != v3.end(); v++)
	{
		cout << *v << ' ';
	}
	cout << endl << "assign的另一种赋值操作" << endl;
	//assign赋值的另一种操作
	vector<int >v4;
	v4.assign(5, 6);
	//迭代器输出数据
	for (vector<int >::iterator v = v4.begin(); v != v4.end(); v++)
	{
		cout << *v << ' ';
	}

}
int main()
{
	//test01();
	//test03();
	//test04();
	//test05();
	//test06();
	//test07();
	//test08();
	//test09();
	test10();
}

vector 容量和大小

  • empty() 判断容器是否为空
  • capacity() 容器的容量
  • size() 返回容器中元素的个数
  • resize(int num) 重新指定容器的长度为num,若容器变长,则以默认值填充新位置,若容器变短,则末尾超出容器长度的元素被删除
  • resize(int num,elem) 重新指定容器的长度为num,若容器变长,则以elem填充新位置,若容器变短,则末尾超出容器长度的元素被删除
void test11()
{
	vector<int >v1;
	for (int i = 0; i <9; i++)
	{
		v1.push_back(i);
	}
	int pos = v1.empty();
	if (pos == 1)//如果POS=1,则说明容器为空
	{
		cout << "容器为空" << endl;
	}
	else {
		cout << "容器不为空" << endl;
	}
	int ca = v1.capacity();
	cout << "v1的容量大小为:" << ca << endl;  //容量计算见反汇编代码
	
	cout << "v1元素的个数为:" << v1.size() << endl;

	v1.resize(15);
	cout << "拓展后的容量:" << v1.capacity() << endl;  //拓展后的容量
	cout << "默认元素拓展:" << endl;
	//迭代器输出数据
	for (vector<int >::iterator v = v1.begin(); v != v1.end(); v++)
	{
		cout << *v << ' ';
	}
	cout <<endl<< "指定元素拓展:" << endl;

	v1.resize(19, 6);
	//迭代器输出数据
	for (vector<int >::iterator v = v1.begin(); v != v1.end(); v++)
	{
		cout << *v << ' ';
	}
}
int main()
{
	//test01();
	//test03();
	//test04();
	//test05();
	//test06();
	//test07();
	//test08();
	//test09();
	//test10();
	test11();
}

容量增加机制(原来的容量 + 原来的容量/2)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yDporck6-1673623666428)(STL(%E4%BA%8C)]%20e3dd03e42809470a9c93b0b4b8b537cd/Untitled.png)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oKDvefxT-1673623666430)(STL(%E4%BA%8C)]%20e3dd03e42809470a9c93b0b4b8b537cd/Untitled%201.png)

vector的插入和删除

  • push_back
  • pop_back
  • insert
  • erase
  • clear
void printVector(vector<int> &v)
{
	for (vector<int> ::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << endl;
}
void test12()
{
	vector <int > v1;
	//元素尾部插入
	v1.push_back(10);
	v1.push_back(12);
	v1.push_back(14);
	v1.push_back(16);
	//输出
	printVector(v1);

	//元素尾部删除
	v1.pop_back();
	printVector(v1);

	//指定位置插入元素
	v1.insert(v1.begin(), 50);
	printVector(v1);

	//指定位置插入指定个数元素
	v1.insert(v1.begin(), 2, 60);
	printVector(v1);

	//删除元素
	v1.erase(v1.begin());
	printVector(v1);

	//指定区间删除,我们删除区间[0,3)
	v1.erase(v1.begin(), v1.begin() + 3);
	printVector(v1);

	//清空容器
	v1.clear();
	printVector(v1);

}
int main()
{
	//test01();
	//test03();
	//test04();
	//test05();
	//test06();
	//test07();
	//test08();
	//test09();
	//test10();
	//test11();
	test12();
}

数据存取

  • at
  • []
  • front()
  • back()
//数据存取
void test13()
{
	vector<int> v;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}

	//使用at查找值
	for(int i = 0;i < v.size();i++)
	{
		cout << v.at(i) << " ";
	}
	cout << endl;
	//使用[]查找值
	for (int i = 0; i < v.size(); i++)
	{
		cout  << v[i] << ' ';
	}
	cout << endl;

	//使用front查找第一个元素
	cout << "v中的第一个元素:" << v.front() << endl;
	//使用back查找最后一个元素
	cout << "v中的最后一个元素:" << v.back() << endl;

}
int main()
{
	//test01();
	//test03();
	//test04();
	//test05();
	//test06();
	//test07();
	//test08();
	//test09();
	//test10();
	//test11();
	//test12();
	test13();
}

互换容器

功能:实现两个容器的数据互换

  • swap
//容器互换
void test14()
{
	vector<int> v1;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	vector<int> v2;
	for (int i = 10; i > 0; i--)
	{
		v2.push_back(i);
	}

	cout << "交换前" << endl;
	cout << "v1" << endl;
	printVector(v1);
	cout << "v2" << endl;
	printVector(v2);

	v1.swap(v2);

	cout << "交换后" << endl;
	cout << "v1" << endl;
	printVector(v1);
	cout << "v2" << endl;
	printVector(v2);
}
int main()
{
	//test01();
	//test03();
	//test04();
	//test05();
	//test06();
	//test07();
	//test08();
	//test09();
	//test10();
	//test11();
	//test12();
	//test13();
	test14();
}

预留空间

  • reserve

只是给分配了内存,不进行初始化,不可以访问

可以减少vector在动态拓展容量的时候的拓展次数

void test15()
{
	int* p = NULL;
	int num = 0;
	vector<int> v;
	v.reserve(10000);//预留空间,
	for (int i = 0; i < 10000; i++)
	{
		v.push_back(i);
		if (p != &v[0]) //统计重新分配内存的次数
		{
			p = &v[0];
			num++;
		}
	}
	cout << num;
}
int main()
{
	//test01();
	//test03();
	//test04();
	//test05();
	//test06();
	//test07();
	//test08();
	//test09();
	//test10();
	//test11();
	//test12();
	//test13();
	//test14();
	test15();
}

deque容器

功能

双端数组,可以对头端进行插入删除操作

deque 与 vector 的区别

  • vector 对于头部的插入删除效率低,数据量越大,效率越低,在头部插入数据时,后面的数据都需要移动
  • deque相对而言,对头部的插入删除速度比vector块
  • vector访问元素的速度比deque要快

deque 的内部工作原理

在deque的内部,存在一个中控器,这个中控器用来维护每个缓冲区的地址,缓冲区用来存储真实数据。

在头部插入数据时,就将数据所在的缓冲区的地址放在当前头部地址的前面,在尾部插入数据就放在后面,使得deque像一片连续的内存空间

deque的容器的迭代器也是支持随机访问

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nSDrizvt-1673623666431)(STL(%E4%BA%8C)]%20e3dd03e42809470a9c93b0b4b8b537cd/Untitled%202.png)

构造函数

  • 默认构造
  • 将某个区间中的元素拷贝到将要创建的对象
  • 用n个某元素初始化
  • 拷贝构造函数
#include<iostream>
#include<deque>
using namespace std;
void print(deque<int> d)
{
	for (int i = 0; i < d.size(); i++)
	{
		cout << d[i] <<  ' ';
	}
	cout << endl;
}
void test01()
{
	deque<int> d1;
	for (int i = 0; i < 10; i++)
	{
		d1.push_back(i);  
	}
	print(d1);
	deque<int> d2(d1);  //拷贝函数
	print(d2);

	deque<int >d3(10, 100);//用10个100填充容器
	print(d3);

	deque<int> d4(d1.begin(), d1.end());
	print(d4);  //区间赋值
}
int main()
{
	test01();
}

赋值操作

基本上和vector一样

  • = 赋值
  • assign赋值

容器大小操作

基本上和vector一样,没有获取容量此函数

  • empty() 判断是否为空
  • size() 返回容器元素个数
  • resize(int num) 重新指定容器长度为num,以默认值填充容器,变短则删除末尾元素
  • resize(int num,elem) 重新指定容器长度为num,以elem填充容器,变短则删除末尾元素

插入和删除

两端插入操作:

  • push_back(elem) 尾部插入元素
  • push_front(elem) 头部插入元素
  • pop_back() 尾部删除元素
  • pop_front() 头部删除元素

指定位置操作:

  • insert(pos,elem) 在POS位置处插入元素elem,返回新数据的位置
  • insert(pos,n,elem) 在POS位置处插入n个elem元素
  • insert(pos,beg,end) 在POS位置插入区间[beg,end) 的数据
  • clear() 清空容器
  • erase(beg,end) 删除区间[beg,end)的数据
  • erase(pos) 删除POS位置的数据
void test02()
{
	deque<int>d;
	for (int i = 0; i < 10; i++)
	{
		d.push_back(i);
	}
	d.erase(d.begin()+3,d.end()); //删除区间[3,10)的数据
	print(d);
//头部插入数据
	d.push_front(100);
//删除d.begin()+1处的数据
	d.erase(d.begin()+1);
	print(d);
 }
int main()
{
	//test01();
	test02();

数据存取

和vector的方式相同

  • at
  • []
  • front()
  • back()

排序操作

功能:对deque容器进行排序

算法:sort(iterator beg,iterator end)

注意:使用sort时需要添加头文件#include

//sort
void test03()
{
	deque<int> d;
	d.push_back(12);
	d.push_back(22);
	d.push_back(14);
	d.push_back(15);
	d.push_back(22);
	d.push_back(42);
	//打印初始值
	print(d);
	//排序操作
	sort(d.begin(), d.end()); 
	//打印排序后的值
	print(d);
}
int main()
{
	//test01();
	//test02();
	test03();
}

stack栈容器

基本概念

stack是一种后进先出的数据结构,只有顶端的元素可以被外界使用,因此它是不可以被遍历的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ng6utLHa-1673623666431)(STL(%E4%BA%8C)]%20e3dd03e42809470a9c93b0b4b8b537cd/Untitled%203.png)

入栈:push

出栈:pop

注意:

使用栈是需要添加头文件

#include<stack>

构造函数

  • 默认构造
  • 拷贝构造

赋值操作

  • =赋值

数据存取

  • push(elem) 向栈顶添加元素
  • pop() 删除栈顶元素
  • top() 返回栈顶元素

大小操作

  • empty()判断栈是否为空
  • size()返回栈的大小
void test04()
{
	stack<int >s;
	s.push(10);
	s.push(11);
	s.push(12);
	s.push(13);
	//输出栈顶元素
	cout << s.top() << endl;
	//弹出栈顶元素
	s.pop();
	//弹出栈顶元素之后的栈顶元素
	cout << s.top() << endl;
}
int main()
{
	//test01();
	//test02();
	//test03();
	test04();
}

queue队列容器

概念:

先进先出的一种数据结构,他有两个出口,可以访问队尾和队头,不允许遍历队列

队列允许从一段新增元素,另一段移除元素

入队:push

出队:pop

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6qol5mpR-1673623666432)(STL(%E4%BA%8C)]%20e3dd03e42809470a9c93b0b4b8b537cd/Untitled%204.png)

注意:

使用队列需要添加头文件

#include<queue>

构造函数

  • 默认构造
  • 拷贝构造

赋值操作

  • = 赋值操作

数据存取

  • push(elem) 往队尾添加元素
  • pop() 从队头删除元素
  • back()返回队尾元素
  • front()返回队头元素

大小操作

  • empty() 判断队列是否为空
  • size() 返回栈的大小
void test05()
{
	queue<int >q;
	q.push(10);
	q.push(11);
	q.push(12);
	q.push(13);
	//输出队头元素
	cout << q.front() << endl;
	//输出队尾元素
	cout << q.back() << endl;
	//弹出队头元素
	q.pop();
	//弹出队头元素之后的队头元素
	cout << q.front() << endl;
}
int main()
{
	//test01();
	//test02();
	//test03();
	//test04();
	test05();
}

list容器

基本概念

链表是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的

功能:

将数据进行链式储存

组成:

链表是由一系列结点组成

结点的组成:一是存储数据元素的数据域,而是存储下一个结点的地址的指针域组成

STL中的链表是一个双向循环链表

优点:

可以对任意位置快速插入或删除元素

动态分配内存,不会造成内存的浪费和溢出

缺点:

遍历速度慢

注意:

list 不能使用下标进行访问

头文件

#include<list>

构造函数

  • 默认构造
  • 拷贝构造
  • 区间初始化
  • n个相同元素初始化
void test06()
{
	list<int> l(5,10);//用5个10初始化链表
	for (list<int>::iterator it = l.begin(); it != l.end();it++)
	{
		cout << *it << ' ';
	}

}

list赋值和交换

  • assign(beg,end) 区间赋值
  • assign(n,elem )相同元素赋值
  • 使用 = 赋值
  • swap(lst) 交换
//swap
void print(list<int>& list1)
{
	for (list<int>::iterator it = list1.begin(); it != list1.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << endl;
}
void test06()
{
	list<int> list1(5,10);
	print(list1);
	list<int> list2(5, 25);
	print(list2);
	//交换元素
	list1.swap(list2);
	print(list1);
	print(list2);
}

大小操作(功能介绍和前面的容器相同)

  • size()
  • empty()
  • resize(num)
  • resize(num,elem)

插入和删除

  • push_back(elem) 尾部添加元素
  • pop_back() //尾部删除元素
  • push_front()容器开头插入元素
  • pop_front() 容器开头删除元素
  • insert(pos,elem) pos位置处插入elem元素,返回数据新的位置
  • insert(pos,n,elem) pos位置处插入n个elem元素
  • insert(pos,beg,end) pos 位置处插入区间[beg,end)
  • clear() 移除容器中所有元素
  • erase(beg,end) 删除区间[gen,end)的元素,返回下一个数据的位置
  • erase(pos) 删除pos位置处的数据,返回下一个数据的位置
  • remove(elem) 删除容器中的所有elem元素

数据存取

  • front()返回第一个元素
  • back() 返回最后一个元素

不可以随机访问

void test07()
{
	list <int>lis;
	lis.push_back(10);
	lis.push_back(20);
	lis.push_back(30);
	lis.push_back(40);
	//访问第一个元素
	cout << "第一个元素:" << lis.front() << endl;
	//访问最后一个元素
	cout << "最后一个元素:" << lis.back() << endl;
	//迭代器访问
	for (list<int>::iterator it = lis.begin(); it != lis.end(); it++)
	{
		//迭代器访问的时候只能支持it++/it--,不可以写it= it+1,
		//也不能写it += 1;
		cout << *it << ' ';
	}
	cout << endl;
}
int main()
{
	//test01();
	//test02();
	//test03();
	//test04();
	//test05();
	//test06();
	test07();
}

list 中反转和排序

  • reverse() 反转链表
  • sort() 链表排序
void test08()
{
	list <int>lis;
	lis.push_back(10);
	lis.push_back(56);
	lis.push_back(35);
	lis.push_back(40);
	lis.push_back(12);
	lis.push_back(43);
	//迭代器访问所有元素
	for (list<int>::iterator it = lis.begin(); it != lis.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << endl;
	//反转
	lis.reverse();
	//输出反转后的
	for (list<int>::iterator it = lis.begin(); it != lis.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << endl;

	//排序
	lis.sort();
	//排序后的数据
	for (list<int>::iterator it = lis.begin(); it != lis.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << endl;
}
int main()
{
	//test01();
	//test02();
	//test03();
	//test04();
	//test05();
	//test06();
	//test07();
	test08();
}

如果想要自己确定排序方式,可以自己写一个函数来实现

bool Compare(int v1, int v2)
{
	//降序
	return v1 > v2;
}
void test08()
{
	list <int>lis;
	lis.push_back(10);
	lis.push_back(56);
	lis.push_back(35);
	lis.push_back(40);
	lis.push_back(12);
	lis.push_back(43);
	//排序
	lis.sort(Compare);
	//排序后的数据
	for (list<int>::iterator it = lis.begin(); it != lis.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

17丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值