C++ Deque的使用

1、前言

deque(['dek])(双端队列)是double-ended queue 的一个不规则缩写。deque是具有动态大小的序列容器,可以在两端(前端或后端)扩展或收缩。

特定的库可以以不同的方式实现deques,通常作为某种形式的动态数组。但是在任何情况下,它们都允许通过随机访问迭代器直接访问各个元素,通过根据需要扩展和收缩容器来自动处理存储。

因此,它们提供了类似于vector的功能,但是在序列的开始部分也可以高效地插入和删除元素,而不仅仅是在结尾。但是,与vector不同,deques并不保证将其所有元素存储在连续的存储位置:deque通过偏移指向另一个元素的指针访问元素会导致未定义的行为。

两个vector和deques提供了一个非常相似的接口,可以用于类似的目的,但内部工作方式完全不同:虽然vector使用单个数组需要偶尔重新分配以增长,但是deque的元素可以分散在不同的块的容器,容器在内部保存必要的信息以提供对其任何元素的持续时间和统一的顺序接口(通过迭代器)的直接访问。因此,deques在内部比vector更复杂一点,但是这使得他们在某些情况下更有效地增长,尤其是在重新分配变得更加昂贵的很长序列的情况下。

对于频繁插入或删除开始或结束位置以外的元素的操作,deques表现得更差,并且与列表和转发列表相比,迭代器和引用的一致性更低。

deque上常见操作的复杂性(效率)如下:

  • 随机访问 - 常数O(1)
  • 在结尾或开头插入或移除元素 - 摊销不变O(1)
  • 插入或移除元素 - 线性O(n)
template < class T, class Alloc = allocator<T> > class deque;

2、初始化

#include <deque> 

deque<int> a; //定义一个int类型的双端队列a
deque<int> a(10); //定义一个int类型的双端队列a,并设置初始大小为10
deque<int> a(10, 1); //定义一个int类型的双端队列a,并设置初始大小为10且初始值都为1
deque<int> b(a); //定义并用双端队列a初始化双端队列b
deque<int> b(a.begin(), a.begin()+3); //将双端队列a中从第0个到第2个(共3个)作为双端队列b的初始值

3、基本操作

deq.size()-容器大小
deq.max_size()-容器最大容量
deq.resize()-更改容器大小
deq.empty()-容器判空
deq.shrink_to_fit()-减少容器大小到满足元素所占存储空间的大小
push_back-尾部增加元素

在当前的最后一个元素之后 ,在deque容器的末尾添加一个新元素。val的内容被复制(或移动)到新的元素。

这有效地增加了一个容器的大小。

void push_back (const value_type& val);
void push_back (value_type&& val);

Example

#include <iostream>
#include <deque>

int main ()
{
  std::deque<int> mydeque;
  int myint;

  std::cout << "Please enter some integers (enter 0 to end):\n";

  do {
    std::cin >> myint;
    mydeque.push_back (myint);
  } while (myint);

  std::cout << "mydeque stores " << (int) mydeque.size() << " numbers.\n";

  return 0;
}
push_front-前端增加元素

在deque容器的开始位置插入一个新的元素,位于当前的第一个元素之前。val的内容被复制(或移动)到插入的元素。

这有效地增加了一个容器的大小。

void push_front (const value_type& val);
void push_front (value_type&& val);

Example

#include <iostream>
#include <deque>

int main ()
{
  std::deque<int> mydeque (2,100);     // two ints with a value of 100
  mydeque.push_front (200);
  mydeque.push_front (300);

  std::cout << "mydeque contains:";
  for (std::deque<int>::iterator it = mydeque.begin(); it != mydeque.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';

  return 0;
}

Output

300 200 100 100
pop_back-删除尾部元素

删除deque容器中的最后一个元素,有效地将容器大小减少一个。

这破坏了被删除的元素。

void pop_back();

Example

#include <iostream>
#include <deque>

int main ()
{
  std::deque<int> mydeque;
  int sum (0);
  mydeque.push_back (10);
  mydeque.push_back (20);
  mydeque.push_back (30);

  while (!mydeque.empty())
  {
    sum+=mydeque.back();
    mydeque.pop_back();
  }

  std::cout << "The elements of mydeque add up to " << sum << '\n';

  return 0;
}

Output

The elements of mydeque add up to 60
pop_front-删除前端元素

删除deque容器中的第一个元素,有效地减小其大小。

这破坏了被删除的元素。

void pop_front();

Example

#include <iostream>
#include <deque>

int main ()
{
  std::deque<int> mydeque;

  mydeque.push_back (100);
  mydeque.push_back (200);
  mydeque.push_back (300);

  std::cout << "Popping out the elements in mydeque:";
  while (!mydeque.empty())
  {
    std::cout << ' ' << mydeque.front();
    mydeque.pop_front();
  }

  std::cout << "\nThe final size of mydeque is " << int(mydeque.size()) << '\n';

  return 0;
}

Output

Popping out the elements in mydeque: 100 200 300
The final size of mydeque is 0
emplace_front-头部插入

在deque的开头插入一个新的元素,就在其当前的第一个元素之前。这个新的元素是用args作为构建的参数来构建的。

这有效地增加了一个容器的大小。

该元素是通过调用allocator_traits::construct来转换args来创建的。

存在一个类似的成员函数push_front,它可以将现有对象复制或移动到容器中。

template <class... Args>
  void emplace_front (Args&&... args);

Example

#include <iostream>
#include <deque>

int main ()
{
  std::deque<int> mydeque = {10,20,30};

  mydeque.emplace_front (111);
  mydeque.emplace_front (222);

  std::cout << "mydeque contains:";
  for (auto& x: mydeque)
    std::cout << ' ' << x;
  std::cout << '\n';

  return 0;
}

Output

mydeque contains: 222 111 10 20 30
emplace_back-尾部插入

在deque的末尾插入一个新的元素,紧跟在当前的最后一个元素之后。这个新的元素是用args作为构建的参数来构建的。

这有效地增加了一个容器的大小。

该元素是通过调用allocator_traits::construct来转换args来创建的。

存在一个类似的成员函数push_back,它可以将现有对象复制或移动到容器中

template <class... Args>
  void emplace_back (Args&&... args);

Example

#include <iostream>
#include <deque>

int main ()
{
  std::deque<int> mydeque = {10,20,30};

  mydeque.emplace_back (100);
  mydeque.emplace_back (200);

  std::cout << "mydeque contains:";
  for (auto& x: mydeque)
    std::cout << ' ' << x;
  std::cout << '\n';

  return 0;
}

Output

mydeque contains: 10 20 30 100 200
insert-任意位置插入元素
//任意位置插入一个元素 
deq.insert(iterator it, const T& x);
//任意位置插入n个相同元素
deq.insert(iterator it, int n, const T& x);
//插入另一个向量的[forst,last]间的数据 
deq.insert(iterator it, iterator first, iterator last);
erase-任意位置删除元素
//任意位置删除一个元素
deq.erase(iterator it);
//删除[first,last]之间的元素
deq.erase(iterator first, iterator last);
//清空所有元素 
deq.clear();

4、迭代器

  • 开始迭代器指针:deq.begin();
  • 末尾迭代器指针:deq.end(); //指向最后一个元素的下一个位置
  • 指向常量的开始迭代器指针: deq.cbegin(); //意思就是不能通过这个指针来修改所指的内容,但还是可以通过其他方式修改的,而且指针也是可以移动的。
  • 指向常量的末尾迭代器指针: deq.cend();
  • 反向迭代器指针,指向最后一个元素: deq.rbegin();
  • 反向迭代器指针,指向第一个元素的前一个元素: deq.rend();
#include <iostream>
#include <deque>

using namespace std;

int main(int argc, char* argv[])
{
    deque<int> deq;
    deq.push_back(1);
    deq.push_back(2);
    deq.push_back(3);

    cout << "*(deq.begin()): " << *(deq.begin()) << endl;
    cout << "*(deq.end()): " << *(--deq.end()) << endl;
    cout << "*(deq.cbegin()): " << *(deq.cbegin()) << endl;
    cout << "*(deq.cend()): " << *(--deq.cend()) << endl;
    cout << "*(deq.rbegin()): " << *(deq.rbegin()) << endl;
    cout << "*(deq.rend()): " << *(--deq.rend()) << endl;
    cout << endl;

    return 0;
}

/*
*(deq.begin()): 1
*(deq.end()): 3
*(deq.cbegin()): 1
*(deq.cend()): 3
*(deq.rbegin()): 3
*(deq.rend()): 1
*/

5、元素访问

deq.front()-访问第一个元素
deq.back()-访问最后一个元素
deq[1]-下标访问

并不会检查是否越界

deq.at(1)-at方法访问

以上两者的区别就是at会检查是否越界,是则抛出out of range异常

参考

https://www.cnblogs.com/linuxAndMcu/p/10260124.html

http://www.cplusplus.com/reference/deque/deque/

  • 16
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
dequeC++标准库中的容器,它是一种双端队列(double-ended queue),可以在两端进行插入和删除操作。在引用中的代码示例中,通过包含头文件<iostream>和<deque>,使用命名空间std来定义了一个名为test的函数。在test函数中,创建了一个deque对象d,并通过d.push_back()函数将元素添加到队列的末尾。然后,使用deque对象d的迭代器构造了一个新的deque对象d2。接着,通过d2.push_back()将10000作为新元素添加到了d2的末尾。最后,通过d.swap(d2)交换了两个deque对象的内容,并通过d.back()获取了d队列中最后一个元素的值,即10000。输出结果为10000。 在引用中的代码示例中,使用deque对象d的成员函数front()和back()分别返回队列的第一个元素和最后一个元素的值。另外,deque对象d的成员函数insert()可以在指定位置插入一个或多个元素,而erase()可以删除指定位置的一个或多个元素。 应用sort算法对deque进行排序时,可以通过包含头文件<algorithm>,定义一个回调函数compare,该函数用于自定义排序规则,可以根据需要按升序或降序排序。然后,使用sort函数对deque进行排序,并通过printDeque函数输出排序后的deque元素。 除此之外,deque还有一些其他函数,如swap()可以交换两个deque对象的内容,assign()可以将一个给定值赋值给deque中的指定位置。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [C++ deque](https://blog.csdn.net/weixin_59141600/article/details/126898400)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [C++ deque用法详解](https://blog.csdn.net/qq_39779233/article/details/107983598)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值