deque
0.deque(双端队列)容器介绍
头文件
#include <deque>
插入
deque 在尾部和头部插入或移除元素非常迅速,在中间插入比较费时,具有双端扩缩能力的序列容器,与 Vector 相反,不是相接存储的,是由一段又一段等长的连续空间构成的
随机存取
支持 [target] 或者 at(target) ,与接口上与 Vector 有许多相似之处。元素地址可能不是连续的,通过运算符重载实现伪连续。
1.deque容器操作
deque 容器之比 Vector 容器多两个函数,其余操作一样
deque.push_front(elem); //容器头部插入一个元素
deque.pop_front(); //删除头部第一个元素
2.deque 对比 vector
- 底层数据结构:
- deque: 双端队列使用多个块(chunks)存储元素,每个块是一个固定大小的数组。在内部,deque 由一系列块组成,每个块都是一个独立的数组,可以在两端进行快速插入和删除。
- vector: 动态数组是一个连续的存储空间,元素在内存中是依次排列的。它支持在末尾的快速插入和删除,但在中间或开头插入或删除元素时可能会导致其他元素的移动。
- 内存分配:
- deque: 由于deque使用多个块,它的内存分配可以更加灵活,每个块可以分配自己的内存。这意味着在插入或删除元素时,不需要移动整个数据结构,而只需移动块。
- vector: 动态数组的内存是连续的,因此在插入或删除元素时,可能需要移动整个数组的元素,导致性能开销。
- 随机访问性能:
- deque: 随机访问性能较差,因为要通过指针跳转到正确的块,然后再在块内进行访问。这可能导致对元素的间接引用。
- vector: 由于元素在内存中是连续排列的,因此支持快速的随机访问。
- 迭代器失效:
- deque: 在deque的头部进行插入或删除不会使迭代器失效,但在中间或尾部进行插入或删除可能会导致某些迭代器失效。
- vector: 在vector中,插入或删除操作可能导致所有在该位置之后的迭代器失效。
- 空间效率:
- deque: 由于使用了多个块,deque可能会占用更多的空间,因为每个块都需要一些额外的管理开销。
- vector: 动态数组通常更为紧凑,因为它不需要额外的块管理开销。
- 插入和删除性能:
- deque: 在两端进行插入和删除的性能较好,而在中间进行插入和删除的性能较差。
- vector: 在末尾进行插入和删除的性能较好,而在中间或开头进行插入和删除的性能较差。
3.什么时候使用?
使用 deque 的情况:
- 频繁在两端进行插入和删除: 如果你需要在序列的两端(头部和尾部)进行高效的插入和删除操作,而不关心中间位置的性能,那么
deque
是一个不错的选择。 - 对迭代器失效有较高容忍度: 如果你的算法对迭代器失效的容忍度较高,因为在 deque 中插入或删除元素可能导致某些迭代器失效,那么可以考虑使用 deque。
- 空间效率相对次要: 如果对空间效率的要求相对较低,因为 deque 可能占用更多的内存,那么可以考虑使用它。
使用 vector 的情况:
- 顺序访问和随机访问较多: 如果你的操作主要涉及顺序访问或随机访问元素,并且你对在两端进行插入和删除的性能有一定的容忍度,那么
vector
是一个更为适合的选择。 - 对迭代器失效敏感: 如果你的算法对迭代器失效敏感,因为在 vector 中插入或删除元素可能导致所有在该位置之后的迭代器失效,那么可以考虑使用 vector。
- 对内存占用有严格要求: 如果内存占用是一个关键因素,因为 vector 通常更为紧凑,那么选择它可能更合适。
- 在末尾进行频繁插入和删除: 如果你的主要操作是在序列末尾进行频繁的插入和删除,而不涉及序列头部或中间的操作,那么
vector
的性能可能更好。
4.总结操作函数
- 构造和初始化:
- 默认构造函数:
deque<T> d;
- 指定初始大小的构造函数:
deque<T> d(size);
- 使用范围构造函数:
deque<T> d(begin, end);
- 拷贝构造函数:
deque<T> d(otherDeque);
- 默认构造函数:
- 元素访问:
at(index)
:返回指定索引位置的元素,抛出越界异常。operator[]
:返回指定索引位置的元素,不进行越界检查。front()
:返回第一个元素的引用。back()
:返回最后一个元素的引用。
- 修改容器:
push_back(value)
:在尾部插入元素。push_front(value)
:在头部插入元素。pop_back()
:移除尾部元素。pop_front()
:移除头部元素。emplace_back(args...)
:在尾部原地构造元素。emplace_front(args...)
:在头部原地构造元素。
- 容器的大小和清空:
size()
:返回容器中元素的个数。empty()
:检查容器是否为空。resize(newSize)
:改变容器的大小,可以增加或减少元素。clear()
:移除所有元素,使容器为空。
- 插入和删除:
insert(position, value)
:在指定位置插入元素。erase(position)
:移除指定位置的元素。erase(begin, end)
:移除指定范围内的元素。
- 迭代器:
begin()
和end()
:返回指向容器起始和结束的迭代器。rbegin()
和rend()
:返回指向容器逆向起始和结束的迭代器。
- 其他操作:
swap(deque1, deque2)
:交换两个deque
的内容。assign(count, value)
:用指定的值替换容器的内容。assign(begin, end)
:用指定范围内的值替换容器的内容。
- Deque 特有操作:
push_front(value)
:在头部插入元素。pop_front()
:移除头部元素。emplace_front(args...)
:在头部原地构造元素。