C ++迭代器用于对数据结构中的元素进行顺序访问或随机访问。因此,对于根据定义不允许顺序或随机访问的数据结构,迭代器没有任何意义。这就是堆栈和队列没有迭代器的原因。另一方面,向量和列表允许对元素进行顺序和/或随机访问,因此迭代器对于导航这些数据结构是有意义的。
堆栈是LIFO(后进先出)数据结构。在任何给定时间,您只能访问堆栈的顶部元素(推送到它上面的最后一个项目)。根据定义,您永远不会顺序遍历堆栈的元素,也不会使用随机访问来获取堆栈中的特定元素。您将元素放在一端,然后将元素放在同一端。您只能访问该顶级元素,并且无权访问其下方的任何内容。你可以把它想象成一堆巨大的书堆在桌子上。要到达最后一本书,您需要从顶部向下移动书籍。要添加图书,您只需将其放在顶部即可。你不能随意访问中间的书。只有您可以看到的书位于顶部。因此,堆栈没有迭代器。
队列是FIFO(先进先出)数据结构。在任何给定时间,您只能在一端(尾部)放置元素,并从另一端(头部)检索元素。根据定义,您永远不会顺序遍历队列的元素,也不会使用随机访问来获取队列中的特定元素。你把元素放在一端,然后从另一端拿走元素。您无法访问两端之间的任何内容。一个新人排在队列中,预约职员可以提前查看此人。不允许队列中的跳转。因此,队列没有迭代器。
这就是这些数据结构的行为和实现方式。您无法从中随机选择/取消选择元素。这就是为什么他们没有迭代器。
向量和列表支持这些随机类型的操作,这就是为什么需要迭代器。
而双端队列是指允许两端都可以进行入队和出队操作的队列,其元素的逻辑结构仍也是线性结构。
延伸
实现
C ++中Stack和Queue的大多数实现都基于链表deque(双端队列),您可以将项添加到结尾或开头,如果您愿意,可以像数组一样使用。
与基于数组的容器(例如和)相比,存在一些性能损失,但是具有额外的好处,即不需要deque中的元素在内存中是连续的。std::vector
std::array
无论如何,并且“适应” ,意味着它们是内部使用的“容器适配器” 。std::stack
std::queue
std::deque、
std::deque
的std ::栈
{top(),push(),pop()}的std ::队列
{push(),pop(),front(),back()}
API
队列和堆栈的一般用途的首选API,例如
- push (queue, stack)
- pop (queue, stack)
- top (stack)
- front (queue)
- back (queue, stack)
- swap (queue, stack)
- emplace (queue, stack)
- empty (queue, stack)
- size (queue, stack)
- relational operators ==, != , <, >, <=, >= (queue, stack)
为什么
我认为这个想法是std :: array,std:vector
和std :: list
提供了足够的通用实用程序,如果你正在实现一个算法
std :: stack或std :: queue你只需要API的简单功能。
C ++对基于数组的容器存在偏见,因为它们非常可靠和快速,并且利用了C ++内存模型,当然还有操作系统分配内存的方式。但是,对于大多数用户应用程序来说,C ++的性能足够高,不会注意到另一个容器,二进制数据存储的紧凑性非常高效。
没有迭代器
提供的迭代器无法访问或正是因为它们的API被有目的地限制。std::deque
std::stack
std::queue
你不应该:
排序堆栈或队列 在中间添加项目
std::stack
并且仅提供对末尾(队列)或顶部(堆栈)的值的访问。它们不需要迭代器,因为没有任何东西需要迭代,没有理由在容器中遍历或搜索,只有结束,因此值是重要的。std::queue
- 删除中间的项目
- 搜索堆栈或队列
- 复制或删除堆栈或队列的范围
算法
存在用于对堆栈和队列中的项目进行排序,搜索,添加,移除的算法,但是它们不是通过随机访问容器中的槽来进行短路的。
堆栈
对于堆栈,您必须展开,弹出顶部,执行操作,然后倒回,按相反顺序推回。
queue
对于队列,您可以旋转值,执行操作,然后反向旋转或向前旋转,直到返回正确的顺序。
模型
在std :: array,std :: vector或std :: list上选择std :: stack或std :: queue的主要原因是为了更接近地模拟使用它们的算法,因为算法要求使用数据那样,只有这样。
您可能正在编写供其他人使用的代码,并且您认为存在滥用其他容器的可能性,因此您希望将API限制为正确使用,并且只能使用堆栈或仅使用传统队列。