【C++】黑马C++泛型编程和STL技术 (5) STL常用容器 --- deque容器

3.3 deque容器

3.3.1 deque容器的基本概念

1. 功能:

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

2. deque与vector区别:

vector对于头部的插入和删除效率低,数据量越大,效率越低。(需要将所有数据后移,将头部位置空出,才可插入数据)
相对而言,deque对头部的插入和删除速度比vector快
vector访问元素的速度比deque快,这和两者内部实现有关。

在这里插入图片描述

3. deque内部工作原理:

deque内部有一个中控器,维护每段缓冲区中的内容,缓冲区中存放真实数据。中控器维护的是每个缓冲区的地址,使得使用deque时像一片连续的内存空间。
和 vector 容器采用连续的线性空间不同,deque 容器存储数据的空间是由一段一段等长的连续空间构成,各段空间之间并不一定是连续的,可以位于在内存的不同区域。
为了管理这些连续空间,deque 容器用数组存储着各个连续空间的首地址。也就是说,数组中存储的都是指针,指向那些真正用来存储数据的各个连续空间。
通过建立数组,deque 容器申请的这些分段的连续空间就能实现“整体连续”的效果。换句话说,当 deque 容器需要在头部或尾部增加存储空间时,它会申请一段新的连续空间,同时在数组的开头或结尾添加指向该空间的指针,由此该空间就串接到了 deque 容器的头部或尾部。
deque 容器的分段存储结构,提高了在序列两端添加或删除元素的效率,但访问速度比vector慢,并且也使该容器迭代器的底层实现变得更复杂。

在这里插入图片描述

4. deque容器迭代器的底层实现:

由于 deque 容器底层将序列中的元素分别存储到了不同段的连续空间中,因此要想实现迭代器的功能,必须先解决如下两个问题:
①迭代器在遍历 deque 容器时,必须能够确认各个连续空间在数组中的位置;
②迭代器在遍历某个具体的连续空间时,必须能够判断自己是否已经处于空间的边缘位置。如果是,则一旦前进或者后退,就需要跳跃到上一个或者下一个连续空间中。

实现:迭代器内部包含4个指针,它们各自的作用为:
cur:指向当前正在遍历的元素;
first:指向当前连续空间的首地址;
last:指向当前连续空间的末尾地址;
node:它是一个二级指针,用于指向数组中存储的指向当前连续空间的指针。

3.3.2 deque构造函数

函数原型:
(和vector的构造函数基本一样,灵活使用即可。)

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

示例:

#include<iostream>
using namespace std;
#include<deque>
// 输出接口
void printDeque(const deque<int> &d)
{
	for(deque<int>::const_iterator it=d.begin();it!=d.end();it++)
	{
		// *it = 100; // const的修饰是的容器中的数据不可修改,此时为只读迭代器
		cout << *it << " ";
	}
	cout << endl;
}
void test01()
{
	// 四种构造方式
	deque<int> d1;	
	for(int i = 0;i<10;i++)
	{
		d1.push_back(i);
	}
	printDeque(d1);
	
	deque<int> d2(d1.begin(),d1.end());
	printDeque(d2);
	
	deque<int> d3(10,100);
	printDeque(d3);
	
	deque<int> d4(d3);
	printDeque(d4);
}

int main()
{
	test01();
	system("pause");
	return 0;
}

输出打印函数中,想要进行只读操作的时候,需要对形参和迭代器同时用const进行修饰
运行结果:

在这里插入图片描述

3.3.3 deque赋值操作

函数原型:

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

示例:

#include<iostream>
using namespace std;
#include<deque>
void printDeque(const deque<int> d)
{
	for(deque<int>::const_iterator it = d.begin();it!=d.end();it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}
void test01()
{
	deque<int> d1;
	for(int i = 0;i<10;i++)
	{
		d1.push_back(i);
	}
	printDeque(d1);
	
	deque<int> d2;
	d2 = d1;
	printDeque(d2);
	
	deque<int> d3;
	d3.assign(d1.begin(),d1.end());
	printDeque(d3);
	
	deque<int> d4;
	d4.assign(10,100);
	printDeque(d4);
}
int main()
{
	test01();
	system("pause");
	return 0;
}

运行结果:
在这里插入图片描述

3.3.4 deque大小操作

函数原型:

deque.empty();					// 判断容器是否为空,空返回true,非空返回false
deque.size();					// 返回容器中元素的个数(大小,当前存放数据个数)
deque.resize(int num);			//	重新指定容器的长度为num
// 若容器变长,则以默认值0填充新位置;如果变短,则末尾超出容器长度的元素被删除
deque.resize(int num,elem);	// 重新指定容器的长度为num
// 若容器变长,则以elem填充新位置;如果变短,则末尾超出容器长度的元素被删除

(deque容器没有容量的概念)

示例:

#include<iostream>
using namespace std;
#include<deque>
void printDeque(const deque<int> &d)
{
	for(deque<int>::const_iterator it = d.begin();it!=d.end();it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}
void test01()
{
	deque<int> d1;
	for(int i= 0;i<10;i++)
	{
		d1.push_back(i);
	}
	printDeque(d1);
	if(d1.empty())
		cout << "该deque容器为空!" << endl;
	else
	{
		cout << "该容器不为空," << endl;
		cout << "容器大小为:" << d1.size() << endl;
	}
	
	d1.resize(15);
	printDeque(d1);
	
	d1.resize(5);
	printDeque(d1);
	
	d1.resize(15,10);
	printDeque(d1);	
}
int main()
{
	test01();
	system("pause");
	return 0;
}

运行结果:

在这里插入图片描述

3.3.5 deque插入和删除

函数原型:

/******** 两端的插入和删除 ********/
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位置的数据,返回下一个数据的位置。

示例:

#include<iostream>
using namespace std;
#include<deque>
void printDeque(const deque<int> d)
{
	for(deque<int>::const_iterator it = d.begin();it!=d.end();it++)
		cout << *it <<" ";
	cout << endl;
}
// 两端操作
void test01()
{
	cout << "两端操作" << endl;
	cout << "=========" << endl;
	deque<int> d1;
	//尾插
	d1.push_back(10);
	d1.push_back(20);
	//头插
	d1.push_front(100);
	d1.push_front(200);
	printDeque(d1);
	// 尾删
	d1.pop_back();
	// 头删
	d1.pop_front();
	printDeque(d1);
}
// 指定位置
void test02()
{
	cout << "Insert指定位置操作" << endl;
	cout << "=========" << endl;
	deque<int> d1;
	d1.push_back(10);
	d1.push_back(20);
	d1.push_front(100);
	d1.push_front(200);
	printDeque(d1);
	// insert
	d1.insert(d1.begin(),1000);
	printDeque(d1);
	d1.insert(d1.begin(),2,100);
	printDeque(d1);
	// insert --- 区间
	deque<int> d2;
	for(int i = 1;i<6;i++)
		d2.push_back(i);
	printDeque(d2);
	d1.insert(d1.begin(),d2.begin(),d2.end());
	printDeque(d1);
}
// 删除操作
void test03()
{
	cout << "删除操作" << endl;
	cout << "=========" << endl;
	deque<int> d1;
	d1.push_back(10);
	d1.push_back(20);
	d1.push_front(100);
	d1.push_front(200);
	printDeque(d1);
	// 删除
	deque<int>:: iterator it = d1.begin();
	it ++ ;	// 迭代器偏移 删除指定位置的元素
	d1.erase(it);
	printDeque(d1);
	d1.erase(d1.begin(),d1.end());
	//d1.clear();
	printDeque(d1);	// 打印一个换行
}
int main()
{
	test01();
	test02();
	test03();
	system("pause");
	return 0;
}

执行结果:
在这里插入图片描述

3.2.6 deque数据存取

函数原型:

at(int idx);	// 返回索引idx所指的数据
operator[];		// 返回索引idx所指的数据
front();		// 返回容器中第一个数据元素
back();			// 返回容器中最后一个数据元素

示例:

#include<iostream>
using namespace std;
#include<deque>
void test01()
{
	deque<int> d;
	d.push_back(10);
	d.push_back(20);
	d.push_back(30);
	d.push_front(100);
	d.push_front(200);
	d.push_front(300);
	// 通过 [] 访问元素并输出
	for(int i=0;i<d.size();i++)
	{
		cout << d[i]<< " ";
	}
	cout << endl;
	// 通过 at 访问元素并输出
	for(int i=0;i<d.size();i++)
	{
		cout << d.at(i)<< " ";
	}
	cout << endl;
	cout << "第一个元素为:" << d.front() << endl;
	cout << "最后一个元素为:" << d.back() << endl;
 }
int main()
{
	test01();
	system("pause");
	return 0;
}

运行结果:
在这里插入图片描述

3.3.7 deque排序

利用算法实现对deque容器进行排序。

函数原型:

sort(iterator beg,iterator end);	//对beg和end区间内元素进行排序

默认的排序规则时从小到大,即升序
对于支持随机访问的迭代器的容器,都可以利用sort算法直接对其进行排序。

示例:

#include<iostream>
using namespace std;
#include<deque>
#include<algorithm> // 包含头文件
void printDeque(const deque<int> &d)
{
	for(deque<int>::const_iterator it=d.begin();it!=d.end();it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}
void test01()
{
	deque<int> d;
	d.push_back(10);
	d.push_back(20);
	d.push_back(30);
	d.push_front(100);
	d.push_front(200);
	d.push_front(300);
	printDeque(d);
	// 排序
	sort(d.begin(),d.end());
	cout << "排序后:";
	printDeque(d);
}
int main()
{
	test01();
	system("pause");
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值