111.C++队列queue

111.C++队列queue和deque

1.queue

1.1queue的简介

queue的中文译为队列,队列是一种数据结构。C语言中队列的定义及初始化以及一些相关操作实现起来较为繁琐,而C++的queue让这些都变得简便易实现。因为C++中有着许多关于queue的方法函数。
队列(queue)最大的特点就是先进先出。就是说先放入queue容器的元素一定是要先出队列之后,比它后进入队列的元素才能够出队列。

使用queue时需要包含头文件:

#include<queue>

1.2queue初始化

格式:

queue<Type, Container> (<数据类型,容器类型>)

初始化时必须要有数据类型,容器可省略,省略时则默认为deque 类型

例子:

queue<int> q;  //使用默认的双端队列为底层容器创建一个空的queue队列对象q,数据元素为int类型。
queue<int> q[20];  //规定队列元素数量
queue<int,list<int>> q1;
queue<int,list<int>> q2(q1);
/*复制构造函数(queue(const queue&)),用一个queue对象创建新的queue对象。 
利用queue对象q1,创建一个以双向链表为底层容器的queue对象q2*/

注意:不能用vector容器初始化queue

因为queue转换器要求容器支持front()、back()、push_back()及 pop_front(),说明queue的数据从容器后端入栈而从前端出栈。所以可以使用deque(double-ended queue,双端队列)和list对queue初始化,而vector因其缺少pop_front(),不能用于queue。

1.3queue中常用的函数

●front():返回 queue 中第一个元素的引用。如果 queue 是常量,就返回一个常引用;如果 queue为空,返回值是未定义的。
●back():返回 queue 中最后一个元素的引用。如果 queue 是常量,就返回一个常引用;如果 queue
为空,返回值是未定义的。
●push(const T& obj):在 queue 的尾部添加一个元素的副本。这是通过调用底层容器的成员函数 push_back()来完成的。
●push(T&& obj):以移动的方式在 queue 的尾部添加元素。这是通过调用底层容器的具有右值引用参数的成员函数push_back() 来完成的。
●pop():删除 queue 中的第一个元素。
●size():返回 queue 中元素的个数。
●empty():如果 queue 中没有元素的话,返回 true。
●emplace():用传给 emplace() 的参数调用 T 的构造函数,在 queue 的尾部生成对象。
●swap(queue<T> &other_q):将当前 queue 中的元素和参数 queue 中的元素交换。它们需要包含相同类型的元素。也可以调用全局函数模板 swap() 来完成同样的操作。

示例代码:

#include<iostream>
#include<queue>
using namespace std;
int main()
{
	queue<int> q1; //定义一个数据类型为int的queue 

	//向队列中加入元素
	q1.push(1);
	q1.push(2); 
	q1.push(3); 
	q1.push(4); 
	queue<int> q2(q1);

	cout << "q1队列中的元素个数为:" << q1.size() << endl;
	//判断队列是否为空 
	if (q1.empty())
	{
		cout << "q1队列为空" << endl;
	}
	else
	{
		cout << "q1队列不为空" << endl;
	}
	cout << "q1队列的队首元素为:" << q1.front() << endl;
	cout << "q1队列的队尾元素为:" << q1.back() << endl;
	//队列中的队首元素出队 
	q1.pop();
	cout << "将q1队列队首元素出队后,现在队列中的元素为2、3、4" << endl;

	// 读取q2队列的头部元素  
	cout << "q2队列的头部元素是:" << q2.front() << endl;

	// 读取q2队列的尾部元素  
	cout << "q2队列的尾部元素是:" << q2.back() << endl;

	//q2调用emplace()
	q2.emplace(5);
	// 遍历队列中的所有元素  
	cout << "q2队列中的所有元素是:";
	while (!q2.empty())
	{
		cout << q2.front() << " ";
		q2.pop();
	}
	cout << endl;
	
	queue<int> q3,q4; //定义一个数据类型为int的queue 

	//向队列中加入元素
	q3.push(1);
	q3.push(2);
	q3.push(3);
	q3.push(4);

	q4.push(5);
	q4.push(4);
	q4.push(3);
	q4.push(2);
	q4.push(1);

	q3.swap(q4);
	// 遍历队列中的所有元素  
	cout << "q3队列中的所有元素是:";
	while (!q3.empty())
	{
		cout << q3.front() << " ";
		q3.pop();
	}
	cout << endl;

	cout << "q4队列中的所有元素是:";
	while (!q4.empty())
	{
		cout << q4.front() << " ";
		q4.pop();
	}
	cout << endl;

	return 0;
}

运行结果:

将元素1、2、3、4一一加入队列中后,队列中现在的元素为:1、2、3、4
队列中的元素个数为:4
队列不为空
队列的队首元素为:1
队列的队尾元素为:4
将队列队首元素出队后,现在队列中的元素为2、3、4

参考:陈童学哦

2.deque

deque,double ended queue即双端队列,是一种在两端均可以扩展或者收缩的序列化容器。deque可以在头部和尾部进行插入和删除操作。

2.1介绍

(1)deque容器的存储结构

与vector容器采用连续的线性空间不同,deque容器存储数据的空间是由一段一段等长的连续空间构成,各段空间之间并不一定是连续的,可以位于在内存的不同区域,使用一个中控器(指针数组)map来指向这些一段一段的空间,如果当前段空间用完了,就添加一个新的空间并将它链接在头部或尾部。deque存储结构如下图所示:

deque特殊的存储结构使得它在头部和尾部插入删除元素的效率非常高,deque可以在头部再加一段空间存储元素,而vector由于采取一段连续存储空间存储元素,所以它在头部插入一个元素需要所有元素向后移动,效率极低。但是也正式因为deque这种特殊的存储结构,使得它的迭代器较于一般的迭代器更为复杂,虽然deque容器的迭代器也支持随机访问,但是访问元素的速度要低于vector。

头文件:
deque是C++ 标准模板库的一部分,因此,想要使用deque,需要在程序中包含头文件deque

#include<deque>

2.2deque定义和初始化

格式:
包含头文件deque之后,我们可以使用下边的格式定义deque:

std::deque<object_type> variable_name;

object_type规定了deque中可以存放哪种类型的元素。
variable_name为deque名。

方式: 定义deque的常用方式如下所示:

deque<Type> v1; 				//v1是一个空deque,可存储元素类型为T,执行默认初始化
deque<Type> v2(v1);			//v2中包含v1中的所有元素
deque<Type> v2 = v1;			//等价于v2(v1)
deque<Type> v3(n,value);		//v3中有n个元素,并且值都为value
deque<Type> v4(n);				//v4包含了n个重复执行了值初始化的对象
deque<Type> v5{a,b,c.....};	//v5包含大括号中的所有元素
deque<Type> v6 = {a,b,c...};	//等价于v5{a,b,c....}

示例代码

#include <deque>
#include <iostream>
using std::cout;
using std::deque;
using std::endl;

int main() 
{
    deque<int> test;
    deque<int> test1 = { 1, 2 };
    deque<int> test2(test1);
    deque<int> test3 = test1;
    deque<int> test4(3, 2);
    deque<int> test5(5);
    deque<int> test6{ 1, 2, 3, 4, 5 };
    deque<int> test7 = { 1, 2, 3, 4, 5, 6 };

    cout << "test:";
    for (auto a : test) 
    {
        cout << a << " ";
    }

    cout << endl << "test1: ";
    for (auto b : test1)
    {
        cout << b << " ";
    }

    cout << endl << "test2: ";
    for (auto b : test2) 
    {
        cout << b << " ";
    }

    cout << endl << "test3: ";
    for (auto b : test3) 
    {
        cout << b << " ";
    }

    cout << endl << "test4: ";
    for (auto b : test4) 
    {
        cout << b << " ";
    }

    cout << endl << "test5: ";
    for (auto b : test5) 
    {
        cout << b << " ";
    }

    cout << endl << "test6: ";
    for (auto b : test6) 
    {
        cout << b << " ";
    }

    cout << endl << "test7: ";
    for (auto b : test7) 
    {
        cout << b << " ";
    }

    return 0;
}

输出:

test:
test1: 1 2
test2: 1 2
test3: 1 2
test4: 2 2 2
test5: 0 0 0 0 0
test6: 1 2 3 4 5
test7: 1 2 3 4 5 6

2.3deque的迭代器

deque中的迭代器包括以下几个,分别为:

●deque.begin():指向deque首元素的迭代器
●deque.end():指向deque尾元素下一个位置的迭代器
●deque.rbegin():指向deque尾元素的反向迭代器,即rbegin()指向尾元素,rbegin-1指向倒数第二个元素
●deque.rend():指向deque头元素前一个位置的反向迭代器,即rend()指向头元素前一个位置元素,rbegin-1指向第一个元素
●deque.cbegin():指向deque首元素的迭代器,与begin()相同,只不过增加了const属性,不能用于修改元素。
●deque.cend():指向deque尾元素下一个位置的迭代器,与end()相同,只不过增加了const属性,不能用于修改元素。
●deque.crbegin():指向deque尾元素的反向迭代器,与rbegin()相同,只不过增加了const属性,不能用于修改元素。
●deque.crend():指向deque头元素前一个位置的反向迭代器,与rend()相同,只不过增加了const属性,不能用于修改元素。

deque迭代器示意图如下:

代码示例如下:

#include <deque>
#include <iostream>

using std::cout;
using std::deque;
using std::endl;

int main()
{
    deque<int> test = { 1, 2, 3, 4 };
    cout << "初始化后deque为: ";

    for (auto num : test)
    {
        cout << num << " ";
    }
    cout << endl;

    // deque.begin()为指向deque头元素的迭代器
    deque<int>::iterator begin_iterator = test.begin();
    cout << "begin() 指向的元素:" << *begin_iterator << endl;

    // deque.end()为指向deque尾元素后一个位置的迭代器,则test.end()-1指向尾元素
    auto end_iterator = test.end();
    cout << "end()-1 指向的元素:" << *(end_iterator - 1) << endl;

    // deque.rbegin()为指向尾元素的迭代器,即反向(r)的头(begin)迭代器
    auto rbegin_iterator = test.rbegin();
    cout << "rbegin() 指向的元素:" << *rbegin_iterator << endl;

    // deque.rend()为指向头元素的前一个位置的迭代器,即反向(r)尾(end)迭代器,则test.rend()-1指向头元素
    auto rend_iterator = test.rend();
    cout << "rend()-1 指向的元素:" << *(rend_iterator - 1) << endl;

    // deque.cbegin()为指向deque头元素的const迭代器
    // 与begin()不同的是返回迭代器类型为deque<int>::const_iterator,不可修改元素
    deque<int>::const_iterator cbegin_iterator = test.cbegin();
    cout << "cbegin() 指向的元素:" << *cbegin_iterator << endl;

    // deque.cend()为指向deque尾元素下一个位置的const迭代器
    // 与end()不同的是返回迭代器类型为deque<int>::const_iterator,不可修改元素
    deque<int>::const_iterator cend_iterator = test.cend();
    cout << "cend()-1 指向的元素:" << *(cend_iterator - 1) << endl;

    // deque.crbegin()为指向尾元素的const迭代器,即反向(r)的const(c)头(begin)迭代器
    auto crbegin_iterator = test.crbegin();
    cout << "crbegin() 指向的元素: " << *crbegin_iterator << endl;

    // deque.crend()为指向头元素下一个位置的const迭代器,即反向(r)的const(c)尾(end)迭代器
    auto crend_iterator = test.crend();
    cout << "crend()-1 指向的元素: " << *(crend_iterator - 1) << endl;

    return 0;
}

输出:

初始化后deque为: 1 2 3 4
begin() 指向的元素:1
end()-1 指向的元素:4
rbegin() 指向的元素:4
rend()-1 指向的元素:1
cbegin() 指向的元素:1
cend()-1 指向的元素:4
crbegin() 指向的元素: 4
crend()-1 指向的元素: 1

2.4deque容器的成员方法

(1)size()——元素个数

要想知道deque中有多少元素,使用deque.size()方法,作用是返回deque中元素的个数。

示例如下:

#include <deque>
#include <iostream>

using std::cout;
using std::deque;
using std::endl;

int main() 
{
    deque<int> mydeque = { 2, 3 };
    cout << "添加元素前mydeque.size() = " << mydeque.size() << endl;
    // 在deque头部插入一个元素5
    mydeque.push_front(5);
    // 在deque尾部插入一个元素5
    mydeque.push_back(1);
    cout << "添加元素后mydeque.size() = " << mydeque.size() << endl;
}

输出:

添加元素前mydeque.size() = 2
添加元素后mydeque.size() = 4

(2)max_size()——最多能容纳元素个数:

要想知道deque最多可以有多少元素,使用deque.max_size()方法,作用是返回deque中最多能容纳元素个数(基本没用过)。

示例如下:

#include <deque>
#include <iostream>

using std::cout;
using std::deque;
using std::endl;

int main() 
{
    deque<int> mydeque = { 2, 3 };
    cout << "mydeque最多可容纳元素个数尾max_size() = " << mydeque.max_size() << endl;
}

输出:

mydeque最多可容纳元素个数尾max_size() = 4611686018427387903

(3)resize(n)——改变deque大小为n

如果想要改变deque的size,使用deque.resize(n)方法,将deque的size改为n。

示例如下:

#include <deque>
#include <iostream>

using std::cout;
using std::deque;
using std::endl;

int main() 
{
    deque<int> mydeque = { 1, 2 };
    // 把mydeque的大小设为5
    mydeque.resize(5);
    cout << "第一次resize后deque中元素为:";
    for (auto a : mydeque) 
    {
        cout << a << " ";
    }
    cout << endl;
    // 把mydeque的大小设为1
    mydeque.resize(1);
    cout << "第二次resize后deque中元素为:";
    for (auto a : mydeque)
    {
        cout << a << " ";
    }
}

输出:

第一次resize后deque中元素为:1 2 0 0 0
第二次resize后deque中元素为:1

可以看到,执行resize(n)后,如果当前deque的size小于n,则会在deque的尾部新添加若干个值为初始值的元素使deque的size扩大到n。如果当前的size大于n,则会从deque尾部移除多余元素使deque的size缩小到n;

(4)empty()——判断deque是否为空

empty()方法用来判断deque中是否有元素,如果有元素,返回false;如果没有元素,返回true。即为空返回true,非空返回false。

示例代码:

#include<iostream>
#include<deque>

using std::cout;
using std::endl;
using std::deque;

int main()
{
    deque<int> mydeque;
    cout << "mydeque是否为空?" << mydeque.empty();
    // 在deque尾部插入一个元素5
    mydeque.push_back(5);
    cout << "\nmydeque是否为空?" << mydeque.empty();
    return 0;
}

输出:

mydeque是否为空?1
mydeque是否为空?0

(5)shrink_to_fit()——要求deque减小容量已适应元素个数 【C++11】

deque减小内存以适配size,即将分配给deque的内存减小到当前deque中元素实际使用的内存大小。由于deque的实现机制大多为一个动态数组,可以保留已被删除的元素的内存空间或者提前分配的额外内存空间以快速插入,因此一个deque分配的内存空间可能比deque保存当前元素所需的内存要多。使用shrink_to_fit()就会释放这些多余暂未被用到的内存。

示例如下:

#include <deque>
#include <iostream>

using std::cout;
using std::deque;
using std::endl;

int main()
{
    deque<int> mydeque;
    // 改变mydeque的大小为100,此时会分配给deque这100个元素所需要的内存
    mydeque.resize(100);
    cout << "mydeque.size() = " << mydeque.size() << "\n";
    // 改变mydeque的大小为10,deque中后90个元素被删除
    // 但是由于deque实现机制,这些元素被删除后,分配给他们的内存空间可以被保留
    // 因此改变mydeque大小为10之后,可能会有额外的内存空间在mydeque中未被使用
    mydeque.resize(10);
    cout << "mydeque.size() = " << mydeque.size() << "\n";
    // 减小mydeque的内存到实际mydeque使用的大小
    mydeque.shrink_to_fit();
}

输出:

mydeque.size() = 100
mydeque.size() = 10

(6) at()——访问deque元素

使用元素的索引来访问deque,其中at(index)中index为索引,必须是合法的。

示例代码:

#include <deque>
#include <iostream>

using std::cout;
using std::deque;
using std::endl;

int main() 
{
    deque<int> mydeque;
    // 初始化mydeque为{1,2,3,4,5}
    for (int i = 1; i <= 5; i++) 
    {
        mydeque.push_back(i);
    }

    cout << "初始化后的mydeque:";
    for (auto num : mydeque)
    {
        cout << num << " ";
    }

    int num2 = mydeque.at(2);
    cout << "\nmydeque中索引为2的元素为:" << num2;

    return 0;
}

输出:

初始化后的mydeque:1 2 3 4 5
mydeque中索引为2的元素为:3

(7)front()和back()——访问deque头尾元素

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

示例代码:

#include<iostream>
#include<deque>

using std::cout;
using std::endl;
using std::deque;

int main() 
{
    deque<int> mydeque{ 1,2,3,4,5,6,7,8 };
    cout << "初始化后的mydeque为:";
    for (auto num : mydeque) 
    {
        cout << num << " ";
    }
    int front = mydeque.front();
    int back = mydeque.back();
    cout << "\nmydeque的头元素为:" << front;
    cout << "\nmydeque的尾元素为:" << back;

    return 0;
}

输出:

初始化后的mydeque为:1 2 3 4 5 6 7 8
mydeque的头元素为:1
mydeque的尾元素为:8

(8)assign()——指定deque元素

assign的作用就是用新的元素替换deque中旧的元素

用法一:deque.assign(num,value)

这种用法会用num个value填充deque,如果操作前deque中有其他元素,会被覆盖掉。

示例如下:

#include <deque>
#include <iostream>

using std::cout;
using std::deque;
using std::endl;

int main()
{
    deque<int> mydeque{ 1, 2, 3, 4 };
    cout << "初始化后的mydeque为:";
    for (auto num : mydeque) 
    {
        cout << num << " ";
    }
    mydeque.assign(3, 2);
    cout << "\nassign之后mydeque为:";
    for (auto num : mydeque) 
    {
        cout << num << " ";
    }
    return 0;
}

输出:

初始化后的mydeque为:1 2 3 4
assign之后mydeque为:2 2 2

用法二:deque.assign(iterator1,iterator2)

这种用法会用两个迭代器iterator1和iterator2之间的元素覆盖deque的元素,迭代器可以是原来deque的迭代器,也可以是其他deque的迭代器,注意区间是左闭右开[iterator1,iterator2),即iterator1指向的元素在区间内,iterator2指向的元素不在区间内,iterator2可以是deque.end()。

示例代码:

#include <deque>
#include <iostream>

using std::cout;
using std::deque;
using std::endl;

int main()
{
    deque<int> mydeque1{ 1, 2, 3, 4 };
    deque<int> mydeque2{ 5, 6, 7, 8 };
    cout << "初始化后的mydeque1为:";
    for (auto num : mydeque1) 
    {
        cout << num << " ";
    }
    cout << "\n初始化后的mydeque2为:";
    for (auto num : mydeque2)
    {
        cout << num << " ";
    }
    // it1指向mydeque1头元素的下一个元素,即第二的元素
    deque<int>::iterator it1 = mydeque1.begin() + 1;
    // it2指向mydeque1尾元素
    deque<int>::iterator it2 = mydeque1.end() - 1;

    // 用[*it1,*it2)的元素替换mydeque2中的元素
    mydeque2.assign(it1, it2);

    cout << "\nassign后的mydeque2为:";
    for (auto num : mydeque2) 
    {
        cout << num << " ";
    }
    return 0;
}

输出:

初始化后的mydeque1为:1 2 3 4
初始化后的mydeque2为:5 6 7 8
assign后的mydeque2为:2 3

用法三:deque.assign(address1,address2)

这种用法会用两个数组元素地址address1和address2之间的元素覆盖deque的元素,注意区间仍是左闭右开[*address1,*address2),即address1指向的元素在区间内,address2指向的元素不在区间内。用法2和用法3示例如下:

示例代码:

#include <deque>
#include <iostream>

using std::cout;
using std::deque;
using std::endl;

int main()
{
    deque<int> mydeque1{ 1, 2, 3, 4 };
    int a[5] = { 10,20,30,40,50 };
    cout << "初始化后的mydeque1为:";
    for (auto num : mydeque1) 
    {
        cout << num << " ";
    }

    // a[2]为30,a[4]为50,则用[a[2],a[4])的元素替换mydeque1中元素
    mydeque1.assign(&a[2], &a[4]);

    cout << "\nassign后的mydeque1为:";
    for (auto num : mydeque1)
    {
        cout << num << " ";
    }
}

输出:

初始化后的mydeque1为:1 2 3 4
assign后的mydeque1为:30 40

(9)push_back()——添加元素(deque尾部)

向deque中添加元素,使用push_back()方法,作用是向deque尾部添加一个元素。示例如下:

示例代码:

#include <deque>
#include <iostream>

using std::cout;
using std::deque;
using std::endl;

int main() 
{
    deque<int> mydeque{ 1, 2, 3, 4 };
    cout << "初始化后的mydeque为:";
    for (auto num : mydeque) 
    {
        cout << num << " ";
    }
    // 在deque尾部插入一个元素8
    mydeque.push_back(8);
    cout << "\n尾部插入一个元素后的mydeque为:";
    for (auto num : mydeque) 
    {
        cout << num << " ";
    }
    return 0;
}

输出:

初始化后的mydeque为:1 2 3 4
尾部插入一个元素后的mydeque为:1 2 3 4 8

(10)push_front()——添加元素(deque头部)

向deque中添加元素,使用push_front()方法,作用是向deque头部添加一个元素。示例如下:

示例代码:

#include <deque>
#include <iostream>

using std::cout;
using std::deque;
using std::endl;

int main() 
{
    deque<int> mydeque{ 1, 2, 3, 4 };

    cout << "初始化后的mydeque为:";
    for (auto num : mydeque) 
    {
        cout << num << " ";
    }
    // 在deque尾部插入一个元素8
    mydeque.push_front(8);

    cout << "\n头部插入一个元素后的mydeque为:";
    for (auto num : mydeque)
    {
        cout << num << " ";
    }

    return 0;
}

输出:

初始化后的mydeque为:1 2 3 4
头部插入一个元素后的mydeque为:8 1 2 3 4

(11)pop_back()——移除deque元素(尾部)

删除deque中的元素,使用pop_back()方法,作用是删除deque尾部的一个元素。示例如下:

示例代码:

#include <deque>
#include <iostream>

using std::cout;
using std::deque;
using std::endl;

int main() 
{
    deque<int> mydeque{ 1, 2, 3, 4 };
    cout << "初始化后的mydeque为:";
    for (auto num : mydeque) 
    {
        cout << num << " ";
    }
    // 删除mydeue尾部一个元素
    mydeque.pop_back();
    cout << "\n尾部删除一个元素后的mydeque为:";
    for (auto num : mydeque)
    {
        cout << num << " ";
    }

    return 0;
}

输出:

初始化后的mydeque为:1 2 3 4
尾部删除一个元素后的mydeque为:1 2 3

(12)pop_front()——删除deque元素(头部)

删除deque中的元素,使用pop_front()方法,作用是删除deque头部的一个元素。示例如下:

示例代码:

#include <deque>
#include <iostream>

using std::cout;
using std::deque;
using std::endl;

int main() 
{
    deque<int> mydeque{ 1, 2, 3, 4 };
    cout << "初始化后的mydeque为:";
    for (auto num : mydeque) 
    {
        cout << num << " ";
    }
    // 删除mydeue头部一个元素
    mydeque.pop_front();
    cout << "\n头部删除一个元素后的mydeque为:";
    for (auto num : mydeque) 
    {
        cout << num << " ";
    }

    return 0;
}

输出:

初始化后的mydeque为:1 2 3 4
头部删除一个元素后的mydeque为:2 3 4

(13)insert()——添加元素(任意位置)

向deque中添加元素。

insert共有三种形式:

  • insert(iterator,value);
  • insert(iterator, num, value);
  • insert(iterator, iterator1, iterator2);

用法一:deque.insert(iterator,value)

使用insert(iterator,value)方法,作用是向iterator迭代器指向元素的前边添加一个元素value,并返回一个迭代器指向新插入的元素。

示例如下:

#include <deque>
#include <iostream>

using std::cout;
using std::deque;
using std::endl;

int main()
{
    deque<int> mydeque{ 1, 2, 3, 4 };
    cout << "初始化后的mydeque为:";
    for (auto num : mydeque) 
    {
        cout << num << " ";
    }
    // it指向mydeque的第二个元素
    deque<int>::iterator it = mydeque.begin() + 1;
    // 使用insert添加一个元素
    deque<int>::iterator itnew = mydeque.insert(it, 10);
    cout << "\n返回的迭代器指向的元素为" << *itnew;
    cout << "\ninsert添加一个元素后的mydeque为:";
    for (auto num : mydeque) 
    {
        cout << num << " ";
    }

    return 0;
}

输出:

初始化后的mydeque为:1 2 3 4
返回的迭代器指向的元素为10
insert添加一个元素后的mydeque为:1 10 2 3 4

用法二:deque.insert(iterator,num,value)

使用insert(iterator,num,value)方法,作用是向iterator迭代器指向元素的前边添加num个元素value,并返回一个迭代器指向新插入的第一个元素.

示例如下:

#include <deque>
#include <iostream>

using std::cout;
using std::deque;
using std::endl;

int main()
{
    deque<int> mydeque{ 1, 2, 3, 4 };
    cout << "初始化后的mydeque为:";
    for (auto num : mydeque) 
    {
        cout << num << " ";
    }

    // it指向mydeque的第二个元素
    deque<int>::iterator it = mydeque.begin() + 1;

    // 定义一个辅助deque
    deque<int> deque2{ 10, 20, 30 };

    // it1指向deque2的第一个元素
    deque<int>::iterator it1 = deque2.begin();

    // it2指向deque2的最后一个元素后一个位置
    deque<int>::iterator it2 = deque2.end();

    // 使用insert在2之前添加[it1,it2)之间的元素
    mydeque.insert(it, it1, it2);

    cout << "\n使用insert插入元素后:";
    for (auto num : mydeque) 
    {
        cout << num << " ";
    }

    return 0;
}

输出:

初始化后的mydeque为:1 2 3 4
使用insert插入元素后:1 20 20 2 3 4

用法三:insert(iterator, iterator1, iterator2);

使用方法,作用是向iterator迭代器指向元素的前边添加[iterator1,iterator2)之间的元素。

示例如下:

#include <deque>
#include <iostream>

using std::cout;
using std::deque;
using std::endl;

int main()
{
    deque<int> mydeque{ 1, 2, 3, 4 };
    cout << "初始化后的mydeque为:";
    for (auto num : mydeque)
    {
        cout << num << " ";
    }

    // it指向mydeque的第二个元素
    deque<int>::iterator it = mydeque.begin() + 1;

    // 定义一个辅助deque
    deque<int> deque2{ 10, 20, 30 };

    // it1指向deque2的第一个元素
    deque<int>::iterator it1 = deque2.begin();

    // it2指向deque2的最后一个元素后一个位置
    deque<int>::iterator it2 = deque2.end();


    // 使用insert在2之前添加[it1,it2)之间的元素
    mydeque.insert(it, it1, it2);

    cout << "\n使用insert插入元素后:";
    for (auto num : mydeque) 
    {
        cout << num << " ";
    }

    return 0;
}

输出:

初始化后的mydeque为:1 2 3 4
使用insert插入元素后:1 10 20 30 2 3 4

(14)erase()——删除元素(任意位置)

erase的作用就是根据传入的迭代器删除deque中的元素,参数为一个迭代器,只删除迭代器指向的元素;参数为两个迭代器,删除两个迭代器之间的元素

用法一:deque.erase(iterator)

这种用法会删除迭代器iterator指向的元素。

示例如下:

#include <deque>
#include <iostream>

using std::cout;
using std::deque;
using std::endl;

int main() 
{
    deque<int> mydeque{ 1, 2, 3, 4 };
    cout << "初始化后的mydeque为:";
    for (auto num : mydeque) 
    {
        cout << num << " ";
    }

    // it指向mydeque的第二个元素
    deque<int>::iterator it = mydeque.begin() + 1;

    // 删除it指向的元素,即2,并返回一个迭代器指向2之后的元素
    deque<int>::iterator itnew = mydeque.erase(it);
    cout << "\n删除元素后返回的迭代器itnew指向的元素为:" << *itnew;
    cout << "\n使用erase删除元素后:";
    for (auto num : mydeque)
    {
        cout << num << " ";
    }

    return 0;
}

输出:

初始化后的mydeque为:1 2 3 4
删除元素后返回的迭代器itnew指向的元素为:3
使用erase删除元素后:1 3 4

用法二:deque.erase(iterator1,iterator2)

这种用法会删除迭代器iterator1指向的元素到iterator2指向元素之间的元素,包括iterator1指向的元素但不包括iterator2指向的元素,即擦除[iterator1,iterator2)。

示例如下:

#include <deque>
#include <iostream>

using std::cout;
using std::deque;
using std::endl;

int main() 
{
    deque<int> mydeque{ 1, 2, 3, 4 };
    cout << "初始化后的mydeque为:";
    for (auto num : mydeque) 
    {
        cout << num << " ";
    }

    // it1指向mydeque的第二个元素
    deque<int>::iterator it1 = mydeque.begin() + 1;
    // it2指向mydeque的最后一个元素后一个位置
    deque<int>::iterator it2 = mydeque.end();

    // 删除[it1,it2)之间的元素,即删除2,3,4
    mydeque.erase(it1, it2);
    cout << "\n使用erase删除元素后:";
    for (auto num : mydeque) 
    {
        cout << num << " ";
    }

    return 0;
}

输出:

初始化后的mydeque为:1 2 3 4
使用erase删除元素后:1

(15)clear()——清空元素

clear的作用就是清空deque中的所有元素

清空deque中所有元素,并且deque的大小变为0。使用clear()方法。

示例如下:

#include <deque>
#include <iostream>

using std::cout;
using std::deque;
using std::endl;

int main() 
{
    deque<int> mydeque{ 1, 2, 3, 4 };
    cout << "初始化后的mydeque为:";
    for (auto num : mydeque) 
    {
        cout << num << " ";
    }

    // 清除mydeque中所有元素
    mydeque.clear();
    cout << "\n使用erase清空元素后mydeque.size() =" << mydeque.size();

    cout << "\n使用erase清空元素后:";
    for (auto num : mydeque) 
    {
        cout << num << " ";
    }

    return 0;
}

输出:

初始化后的mydeque为:1 2 3 4
使用erase清空元素后mydeque.size() =0
使用erase清空元素后:

(16)swap()——交换元素

swap的作用就是交换两个deque的元素

交换两个deque的元素,使用swap()方法,deque1.swap(deque2),两个deque存储的元素类型必须相同,元素个数可以不同。

示例如下:

#include <deque>
#include <iostream>

using std::cout;
using std::deque;
using std::endl;

int main()
{
    deque<int> mydeque1{ 1, 11, 111, 1111 };
    deque<int> mydeque2{ 2, 22, 222 };
    cout << "初始化后的mydeque1为:";
    for (auto num : mydeque1)
    {
        cout << num << " ";
    }

    cout << "\n初始化后的mydeque1为:";
    for (auto num : mydeque2) 
    {
        cout << num << " ";
    }

    // 交换mydeque1和mydeque2的元素
    mydeque1.swap(mydeque2);

    cout << "\n使用swap交换元素后mydeque1:";
    for (auto num : mydeque1) 
    {
        cout << num << " ";
    }

    cout << "\n使用swap交换元素后mydeque2:";
    for (auto num : mydeque2)
    {
        cout << num << " ";
    }

    return 0;
}

输出:

初始化后的mydeque1为:1 11 111 1111
初始化后的mydeque1为:2 22 222
使用swap交换元素后mydeque1:2 22 222
使用swap交换元素后mydeque2:1 11 111 1111

(17)emplace()——插入元素 【C++11】

向deque中添加元素,使用emplace(iterator,value)方法,作用是向iterator迭代器指向元素的前边添加一个元素value。返回一个迭代器,指向新添加的元素。

示例如下:

#include <deque>
#include <iostream>

using std::cout;
using std::deque;
using std::endl;

int main() 
{
    deque<int> mydeque{ 1, 2, 3, 4 };
    cout << "初始化后的mydeque1为:";
    for (auto num : mydeque) 
    {
        cout << num << " ";
    }

    // it指向mydeque第二个元素,即2
    deque<int>::iterator it = mydeque.begin() + 1;

    // 向it指向元素(2)前插入元素10,并返回指向10的迭代器
    deque<int>::iterator it1 = mydeque.emplace(it, 10);
    cout << "\n第一次插入后返回的迭代器it1指向元素为:" << *it1;

    // 向it1指向元素(10)前插入元素20,并返回指向20的迭代器
    deque<int>::iterator it2 = mydeque.emplace(it1, 20);
    cout << "\n第二次插入后返回的迭代器it2指向元素为:" << *it2;

    // 向mydeque尾部插入元素30
    mydeque.emplace(mydeque.end(), 30);
    cout << "\n三次插入元素后,mydeque为:";
    for (auto num : mydeque) 
    {
        cout << num << " ";
    }

    return 0;
}

输出:

初始化后的mydeque1为:1 2 3 4
第一次插入后返回的迭代器it1指向元素为:10
第二次插入后返回的迭代器it2指向元素为:20
三次插入元素后,mydeque为:1 20 10 2 3 4 30

emplace和insert的区别:
emplace和insert插入元素最大的区别就是emplace不会产生不必要的变量,使用insert插入元素时,需要申请内存空间创建临时对象,而申请内存空间就需要消耗一定时间;而使用emplace插入元素时,直接在原来容器的内存空间上 ,调用构造函数,不需要额外申请内存空间,就节省了很多时间,效率较高。

(18)emplace_back()——在deque尾部插入元素 【C++11】

在容器尾部生成一个元素。和 push_back() 的区别是,该函数直接在容器尾部构造元素,省去了复制移动元素的过程。示例如下:

示例代码:

#include <deque>
#include <iostream>

using std::cout;
using std::deque;
using std::endl;

int main() 
{
    deque<int> mydeque{ 1, 2, 3, 4 };

    cout << "初始化后的mydeque为:";
    for (auto num : mydeque)
    {
        cout << num << " ";
    }
    // 在deque尾部插入一个元素10
    mydeque.emplace_back(10);

    cout << "\n尾部插入一个元素后的mydeque为:";
    for (auto num : mydeque)
    {
        cout << num << " ";
    }

    return 0;
}

输出:

初始化后的mydeque为:1 2 3 4
尾部插入一个元素后的mydeque为:1 2 3 4 10

(19)emplace_front()——在deque尾部插入元素 【C++11】

在容器头部生成一个元素。和 push_front() 的区别是,该函数直接在容器头部构造元素,省去了复制移动元素的过程。示例如下:

示例代码:

#include <deque>
#include <iostream>

using std::cout;
using std::deque;
using std::endl;

int main()
{
    deque<int> mydeque{ 1, 2, 3, 4 };

    cout << "初始化后的mydeque为:";
    for (auto num : mydeque) 
    {
        cout << num << " ";
    }
    // 在deque头部插入一个元素10
    mydeque.emplace_front(10);

    cout << "\n头部插入一个元素后的mydeque为:";
    for (auto num : mydeque) 
    {
        cout << num << " ";
    }
    
    return 0;
}

输出:

初始化后的mydeque为:1 2 3 4
头部插入一个元素后的mydeque为:10 1 2 3 4

参考:deque用法深度解析,一篇文章弄懂deque容器各种操作

posted @ 2023-07-21 10:32  CodeMagicianT  阅读(902)  评论(0编辑  收藏  举报