deque(双端队列)和 vector 区别及 deque 详解

注:想要理解本篇博客,需要读者有基本的 vector 的知识,请看博主的另一篇文章: https://blog.csdn.net/qq_41291253/article/details/89840185

一、deque 简介

(1)deque:双端队列

template > class deque;


//T - 元素的类型。别名为成员类型deque :: value_type。
//alloc - 用于定义存储分配模型的分配器对象的类型。默认情况下,使用allocator类模板,该模板定义最简单的内存分配模型,并且与值无关。

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

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

因此,deque提供类似于vector的功能,但在序列的开头也有可以插入和删除元素,而不仅仅是在其结尾。但是,与vector不同,deques不能保证将其所有元素存储在连续的存储位置中:deque通过将指针偏移(如p++,p 为指针类型)到另一个元素来访问 该元素会导致未定义的行为。

vector和deques 两者提供了一个非常相似的接口,可以用于类似的目的,但内部是以完全不同的方式工作:虽然vector使用需要偶尔重新分配用于增长的单个数组,但是双端队列的元素可以分散在不同的块中存储,容器在内部保存必要的信息,以便在恒定时间内通过统一的顺序接口(通过迭代器)直接访问其任何元素。因此,deques在内部比vector稍微复杂一些,但是这允许deque在非常长的序列中更有效地扩展,但是在这种情况下,重新分配内存变得更加耗费时间。例如,对于 6M 数据,vector 需要连续的 6M 内存;deque 可能需要 6 个 1M 内存。

对于在开始或结束之外的位置频繁插入或删除元素的操作,deque的性能更差,而且迭代器和引用的一致性比list和forward list差。

(2)容器属性

序列:序列容器中的元素按严格的线性顺序排序。各个元素按其顺序访问它们的位置。

动态数组:通常实现为动态数组,它允许直接访问序列中的任何元素,并在序列的开头或结尾提供相对快速的元素添加/删除。

分配器感知:容器使用allocator对象来动态处理其存储需求。

(3)deque和 vector 区别

  • deque 两端都能快速插入和删除元素,复杂度不变;而 vector 只能在尾端快速插入元素,在首端插入元素需要移动所有数据,时间复杂度为n。
  • 因内存区域不连续,所以++it,--it 操作可能会出错,而 vector 是连续存储,则不存在这一现象。
  • 元素的存取和迭代器的动作相对 vector 慢。
  • 因为deque使用不止一块内存,所以deque的max_size()可能更大。
  • 双端队列的元素可以分散在不同的块中存储,容器在内部保存必要的信息,以便在恒定时间内通过统一的顺序接口(通过迭代器)直接访问其任何元素。因此,deques在内部比vector稍微复杂一些,但是这允许deque在非常长的序列中更有效地扩展,但是在这种情况下,重新分配内存变得更加耗费时间。
  • 除了头尾两端,在任何地方安插或删除元素,都将导致指向deque元素的所有pointers、references、iterators失效。
  •  deque的内存区块不再被使用时,会自动被释放。deque的内存大小是可自动缩减的。

二、成员函数

deque  member function  
iterators: capacity: element access modifiers:
begin 返回容器中第一个元素的迭代器 size 返回容器中元素数量 operator[ ] 获取指定位置元素 assign 分配元素
end 返回容器中最后一个元素的迭代器 max_size 返回容器能存储最大元素数量 at 获取指定位置元素 push_back 在队尾压入元素
rbegin 返回容器中最后一个元素的反向迭代器 resize 调整容器大小以使其包含指定大小元素 front 获取队头元素 push_front 在队头压入元素
rend 返回容器中第一个元素的反向迭代器 empty 判断容器是否为空 back 获取队尾元素 pop_back 弹出队尾元素
            pop_front 弹出队首元素
            insert 在指定位置插入元素
            erase 删除指定位置元素
            swap 交换两个队列元素
            clear 清空队列

注:标红为详解函数,其他函数都和 vector 用法相同,这里不在赘述,想要学习的读者,请自行查看 https://blog.csdn.net/qq_41291253/article/details/89840185

三、函数详解 

std::deque::begin

将迭代器返回到开头,返回指向deque容器中第一个元素的迭代器。

请注意,与成员deque :: front不同,它返回对第一个元素的引用,此函数返回指向它的随机访问迭代器。

如果容器为空,则不应取消引用返回的迭代器值。取消引用在这里可以通过指针来理解:int a = 5;  int* p;  p = &a;  cout << *p; 我们称 p 引用 a 的地址(p的值为 a 的地址),称*p 为取消引用 a 的值(*p 的值为 a 的值,即 5)。所以这句话意思是,如果容器为空,则 begin 对应的迭代器存储的内容为空(相当于a为空),如果取消引用返回迭代器的值会出错(即 *p 会报错,因为 p 指向的地址内容为空)。

deque(双端队列)和 vector 区别及 deque 详解_第1张图片

// deque::begin
#include 
#include 

int main ()
{
  std::deque mydeque;

  for (int i=1; i<=5; i++) mydeque.push_back(i);

  std::cout << "mydeque contains:";

  std::deque::iterator it = mydeque.begin();

  while (it != mydeque.end())
    std::cout << ' ' << *it++;

  std::cout << '\n';

  return 0;
}

//output
//mydeque contains: 1 2 3 4 5

 std::deque::push_frond / pop_frond

void push_front(const value_type&val);

//val - 要复制(或移动)到插入元素的值。
//成员类型value_type是容器中元素的类型,在deque中定义为其第一个模板参数(T)的别名。

void pop_front();

push_frond:在开头插入元素,在deque容器的开头插入一个新元素,就在它当前的第一个元素之前。val的内容被复制(或移动)到插入的元素。这将容器尺寸增加了一位。

pop_front:删除deque容器中的第一个元素,将其大小减小一位。这会破坏已删除的元素。

// deque::push_front
#include 
#include 

int main ()
{
  std::deque 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::iterator it = mydeque.begin(); it != mydeque.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';

  return 0;
}

//output
//300 200 100 100
// deque::pop_front
#include 
#include 

int main ()
{
  std::deque 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

 

你可能感兴趣的:(#,C++容器详解,deque详解,双端队列,deque,和,vector,区别)