向量和栈的主要区别是什么?

32

两者都像堆栈一样。它们都具有推入(push)和弹出(pop)操作。

它们的区别在于内存布局吗?


1
栈(Stack)的默认容器是双端队列(deque) - class Container = deque<T> - Jesse Good
@Jesse 有支持这个观点的链接吗?向量的默认容器是什么? - Aquarius_Girl
这里是一个链接到MSDN的网页。你还应该获取C++标准草案的pdf副本,其中包含了定义。Vector是标准STL容器之一,而stack则是使用标准容器之一的特化。 - Jesse Good
6个回答

23

std::vector相比于std::stack具有多个可访问性和修改操作。在std::stack的情况下,您可能只能以系统方式执行操作,其中可以在最后一个元素上方push()或弹出pop()最后一个元素。

std::vector在这方面更加灵活,它具有多个操作,其中可以在中间进行insert()erase()

主要的问题是,std::stack需要提供基础容器。默认情况下,它是std::deque,但也可以是std::vectorstd::list
另一方面,std::vector保证是一个连续的数组,可以使用operator []进行访问。


你说:“重点是,std::stack需要提供底层容器。”但是这个例子并没有展示额外的提供容器的努力?http://www.cplusplus.com/reference/stl/stack/push/ - Aquarius_Girl
3
@AnishaKaul,这是因为默认情况下,它是这样的:template < class T, class Container = deque<T> > class stack;。所以如果你不提供任何容器,它就会假定为std::deque。请参见我在答案中发布的链接以获取更多信息。 - iammilind
好的,谢谢,容器可以更改!很好。Vector的默认容器是通过new创建的动态数组? - Aquarius_Girl
1
@AnishaKaul,std::vector 是一个独立的容器。它使用 std::allocator,并且可能会使用 new[] - iammilind
1
@Anisha:当人们使用“容器”这个词时,通常只指STL容器。这里有一个链接列出了它们(尽管在C++11中添加了其他容器)。 - Jesse Good
@Jesse 我看过那个链接,我也是在指STL容器。 - Aquarius_Girl

18

我不了解所有实现细节,但根据这个链接,栈是一个容器适配器。它确保底层容器(可以是向量、链表或双端队列)工作为一个栈,即只允许推入和弹出,而不允许随机访问。

所以,向量可以作为栈来使用,但栈不能像向量一样使用,因为您无法在随机位置插入或获取元素。


1
+1 对于重要的观点。STL包含几个容器适配器,它们不遵守容器的一般要求,因为...它们不是容器。 - Matthieu M.

9

stack是一个栈。它只能进行推入和弹出操作。而vector可以做其他的事情,比如在中间插入元素。这增加了灵活性,但降低了保证。

例如,在栈中,如果你将A和B依次推入栈中,那么保证它们会以B、A的顺序被弹出。但是vector不能保证这一点。


没错,我刚看到 vector 有一个 erase 函数可以从中间删除元素。而栈没有这样的功能。:) 所以,vector 是一个灵活的栈。 - Aquarius_Girl
@Anisha:不,这是一种错误的假设。如果是这样的话,链表、简单数组、双端队列都可以被称为堆栈,对吗?但是堆栈是为容器或数据结构定义的一组属性。如果您的实现符合为堆栈定义的属性,则可以从上述数据结构中创建堆栈。 - Arunmu
@ArunMu 实际上,我所指的“堆栈”是指名为“堆栈”的“容器”。 - Aquarius_Girl
@AnishaKaul:哦。我只是在说,即使您为 stack 添加 operator[] 函数,它也不再符合标准的栈定义 :)。只是说一下... - Arunmu
@ArunMu,我们可以将用户定义的函数[]添加到容器堆栈中吗? - Aquarius_Girl
1
@AnishaKaul:如果你想继承堆栈容器,那就不要了... STL容器没有虚析构函数。而且我认为按照STL的实现,这将是一项艰巨的任务... 为了保持堆栈属性,必须正确处理。 - Arunmu

2

栈基本上是向量的一种特殊情况。理论上,向量可以随意增长。您可以在向量中的任何索引处删除元素。然而,在栈的情况下,只能在其顶部删除和插入元素(因此是向量的一种特殊情况)。

实际上,在许多提供栈实现的库中,它们通常继承自向量类/结构。我不确定,但我认为STL(C ++)就是这样做的。


1
STL 是一个老东西;你可能指的是标准库。而且,它的 stack 没有被定义为继承自 vector;它是一个模板适配器,默认情况下使用 deque,可以选择 vector 作为选项。 - underscore_d

1

正如cplusplus.com所建议:

堆栈是一种容器适配器,专门设计用于LIFO上下文(后进先出),其中元素仅从容器的一端插入和提取。

关键词在于only,即元素只能从容器的一端插入和提取。

你说向量和堆栈都像堆栈一样,但这只是部分正确。向量可以像堆栈一样运作,但它们也可以非常不像堆栈,例如允许您在任何索引处插入,访问任何元素,迭代整个结构等等。

堆栈接受一个容器(例如向量)并且只允许堆栈式的交互。这有效地保证与容器的所有交互都将遵守LIFO:只有最近添加的元素才能被访问或删除。

如果您需要一个类似堆栈的容器,那么如果对于它的行为必须是纯粹的堆栈,您应该使用堆栈。如果您想要类似堆栈的行为,但也可能想要做像迭代元素或修改任意位置的元素等其他操作,则应使用向量。

0

我认为主要的区别在于向量是基于范围的容器。由于其成员函数(如begin和end),它可以很容易地使用。向量可以很容易地使用{}形式进行初始化。我们可以使用现代C++的新功能,如基于范围的循环。

vector<int> vec{ 7, 3, 1, 9, 5 };
for ( auto &i : vec ) {
    std::cout << i << std::endl;
}

虽然 std::stack 不支持此操作。


但是选择使用 std::stack 的人已经知道他们不关心基于范围的迭代;相反,他们想要一个简洁的接口来按照明确定义的顺序推入和弹出元素。 - underscore_d

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接