C++ STL deque容器 基本概念 构造函数 赋值操作 容器大小操作

deque容器

1 deque容器基本概念

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

deque与vector区别:

  • vector(单端数组,左闭右开),对于头部的插入删除效率低,数据量越大,效率越低。比如头部插入新数据,需要从头部开始往后移动,预留内存空间再插入新数据
  • deque相对而言,对头部的插入删除速度回比vector
  • vector访问元素时的速度会比deque快,这和两者内部实现有关

deque容器
在这里插入图片描述
front():第一个元素,back():最后一个元素;
begin():起始迭代器,end():结束迭代器;
push_front():头部插入数据,pop_front():头部删除数据;
push_back():尾部插入数据,pop_back():尾部删除数据;
insert():插入数据,对外接口。

deque内部工作原理:

deque内部有个中控器维护每段缓冲区中的节点(内容),缓冲区中存放真实数据

中控器维护的是每个缓冲区的地址,使得使用deque时像一片连续的内存空间

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

在这里插入图片描述

说明:
中控器中维护缓冲区的地址,缓冲区存放有效的数据。
在头部插入时,首地址是0x01,那么新数据首先在这个地址指向的缓冲区插入,当内存不够时,会再找新的缓冲区继续在头部插入数据,新缓冲的地址0x00也会在中控器中存入并维护;
同样地,在尾部插入时,首地址是0x03,新数据在这个地址指向的缓冲区插入,当内存不够时,会再找新的缓冲区继续在尾部插入数据,新缓冲的地址0x04也会在中控器中存入并维护。因此,deque可以实现快速的头部、尾部插入数据。

和vector数组相比,deque访问元素时没有vector快。比如访问第一个元素ele1,中继器要通过这个元素缓冲区的地址0x00访问,访问下一个元素时,要再通过地址0x01才能访问。也就是说,访问元素时,需要通过元素所在的缓冲区来访问。因此,deque头尾插入数据速度快,但是访问数据效率低,但也可以跳跃访问。

2 deque构造函数

功能描述: deque容器构造

函数原型:

  • deque<T> deqT;——————默认构造形式
  • deque(beg, end);——————构造函数将[beg, end)区间中的元素拷贝给本身。
  • deque(n, elem);——————-构造函数将n个elem拷贝给本身。
  • deque(const deque &deq);——-拷贝构造函数

代码示例:

void test1()
{
	int len = 50;

	//1、默认构造形式
	deque<int> d1;
	for (int i = 1; i < 16; ++i)
	{
		d1.push_back(i);//尾插
	}
	cout << "默认构造\td1:" << endl;
	printDeque(d1); cout << string(len, '-') << endl;
	//for (int i = 11; i < 16; ++i)
	//{
	//	d1.push_front(i);//头插
	//}
	//cout << "头插 d1:" << endl;
	//printDeque(d1); cout << string(len, '-') << endl;

	//2、[beg, end)区间构造 左闭右开
	deque<int> d2(d1.begin(), d1.end());
	cout << "区间构造\td2:" << endl;
	printDeque(d2); cout << string(len, '-') << endl;

	//3、n个elem拷贝构造
	deque<int> d3(13, 15);
	cout << "n个elem拷贝构造\td3:" << endl;
	printDeque(d3); cout << string(len, '-') << endl;

	//4\拷贝构造
	deque<int> d4(d3);
	cout << "拷贝构造\td4:" << endl;
	printDeque(d4); cout << string(len, '-') << endl;
}

在这里插入图片描述
说明:
以上的构造方法和vector中的一样,不赘述。要注意的是,如果想要容器是一个只读状态,容器可以加入const修饰,相应地,迭代器也要换成有const修饰的迭代器,如下所示。

//打印输出 加入const修饰迭代器 只读不写
void printDeque(const deque<int>& d)
{
	for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
	{
		//*it = 100;//const_iterator 容器数据不可以被修改
		cout << *it << "  ";
	}
	cout << endl;
}

在这里插入图片描述

解释:
在打印函数中,有可能会对迭代器进行一个写操作,修改其中数据。如果想要这个打印函数只读不写,那么可以加入const修饰deque容器,即const deque<int>& d。如果迭代器还是原来deque<int>::iterator的定义方式,会提示“无法从const iterator…到iterator转换…”。因此,需要把起始迭代器也做修改,换成deque<int>::const_iterator,此时起始迭代器就不能被修改了,变成只读不写的状态。

总结: deque容器和vector容器的构造方式几乎一致,灵活使用即可

3 deque赋值操作

功能描述: 给deque容器进行赋值

函数原型:

  • deque& operator=(const deque &deq); ——————重载等号操作符
  • assign(beg, end);——————————————将[beg, end)区间中的数据拷贝赋值给本身。
  • assign(n, elem);——————————————-将n个elem拷贝赋值给本身。

代码示例:

void printDeque(const deque<int>& d)
{
	for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
	{
		cout << *it << "  ";
	}
	cout << endl;
}

void test1()
{
	int len = 50;
	deque<int> d1;
	for (int i = 1; i < 16; ++i)
	{
		d1.push_back(i);//尾插
	}
	cout << "d1:" << endl;
	printDeque(d1); cout << string(len, '-') << endl;

	//1、operator=赋值
	deque<int> d2;
	d2 = d1;
	cout << "operator=赋值\td2:" << endl;
	printDeque(d2); cout << string(len, '-') << endl;

	//2、assign区间赋值 [beg, end)
	deque<int> d3;
	d3.assign(d2.begin(), d2.end());
	cout << "assign区间赋值\td3:" << endl;
	printDeque(d3); cout << string(len, '-') << endl;

	//3、assign n个elem拷贝赋值
	deque<int> d4;
	d4.assign(13, 15);
	cout << "assign n个elem拷贝赋值\td4:" << endl;
	printDeque(d4); cout << string(len, '-') << endl;
}

在这里插入图片描述
总结: deque赋值操作也与vector相同,需熟练掌握

4 deque大小操作

功能描述: 对deque容器的大小进行操作

函数原型:

  • deque.empty();———————–判断容器是否为空

  • deque.size();————————-返回容器中元素的个数

  • deque.resize(num);——————重新指定容器的长度为num,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。

  • deque.resize(num, elem);————重新指定容器的长度为num,若容器变长,则以elem值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。

注意:

vector容器中是有容量这个概念的,因为这是一个单端数组,左闭右开的范围,容量有限,并且vector有对外的接口capacity()。

但在deque容器中,是没有容量这个概念的,因为这是一个双端数组,可以无限动态扩展 deque容器,左开右开的范围,容量无限 ,所以没有capacity()这个对外接口,只有 大小 这个概念和接口 size()和resize()

代码示例:

void printDeque(const deque<int>& d)
{
	for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
	{

		//*it = 100;//const_iterator 容器数据不可以被修改
		cout << *it << "  ";
	}
	cout << endl;
}

void test1()
{
	int len = 60;

	deque<int> d1(13, 15);
	cout << "d1容器resize前\t" << endl << "d1:  "; 
	printDeque(d1);
	if (d1.empty())
	{
		cout << "容器为空!" << endl;
	}
	else
	{
		cout << "容器的大小:" << d1.size() << endl;
	}

	cout << string(len, '-') << endl;
	//重新指定大小  比原来小
	d1.resize(7);//删除超出新大小的数据
	cout << "d1容器resize后\t" << endl << "d1:  ";
	printDeque(d1);
	if (d1.empty())
	{
		cout << "容器为空!" << endl;
	}
	else
	{
		cout << "容器的大小:" << d1.size() << endl;
	}

	cout << string(len, '-') << endl;
	//重新指定大小  比原来大
	d1.resize(13);//默认值0填充
	cout << "d1容器resize后\t" << endl << "d1:  ";
	printDeque(d1);
	if (d1.empty())
	{
		cout << "容器为空!" << endl;
	}
	else
	{
		cout << "容器的大小:" << d1.size() << endl;
	}

	cout << string(len, '-') << endl;
	//重新指定大小  比原来大
	d1.resize(16, 15);//指定值填充
	cout << "d1容器resize后\t" << endl << "d1:  ";
	printDeque(d1);
	if (d1.empty())
	{
		cout << "容器为空!" << endl;
	}
	else
	{
		cout << "容器的大小:" << d1.size() << endl;
	}
	cout << endl;
}

在这里插入图片描述
注意: resize时,比原来小,删除超出部分;比原来大,可以指定值填充,否则默认值0填充。

总结:

  • deque没有容量的概念
  • 判断是否为空 — empty
  • 返回元素个数 — size
  • 重新指定个数 — resize
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值