如何在一个数组中实现两个堆栈?


15

我首先要说这不是一个作业问题。我正在阅读算法简介-著名的CLRS文字,以成为更好的程序员。我正在尝试解决本书中自己提出的问题和练习。

我试图解决锻炼; Tibial 10.1-2第10章基本数据结构从CLRS第二版。其状态如下:

说明如何在一个数组A [1..n]中实现两个堆栈,除非两个堆栈中的元素总数为n,否则两个堆栈都不会溢出。PUSH和POP操作应在O(1)时间中运行。

到目前为止,我想出的解决方案是:

让数组A [1..n]实现两个堆栈:S1 [1..i]S2 [i..n]

对于PUSH-S1PUSH-S2操作,如果堆栈“已满”,则开始将元素推入另一个堆栈(例如,当尝试将新元素推入时,如果堆栈S1已满,则将该元素推入堆栈S2,反之亦然)。

这种方法的问题是我将无法可靠地进行POP-S1POP-S2,因为无法“记住”哪个元素属于哪个堆栈。如果堆栈的元素是(键,值)对,键是堆栈号,那么要弹出一个元素,在最坏的情况下,我必须搜索i或(ni)次-这将是O(n )(如果我在这里错了,请随时纠正我),它不是O(1)

我已经在这个问题上花了很长时间了。我在正确的轨道上吗?有人可以给我解决该问题的可能指示吗?

通常,我应该如何“思考”这些问题?还是只有真正有才智的人才能解决这类问题?解决/解决此类问题(例如获得经验)是否可以帮助我变得更好?

我在等待启蒙。


3
“解决/解决这样的问题(例如获得经验)是否可以帮助我变得更好?” 以我的经验,确实是这样。如果没有其他问题,您将以多种方式思考该问题,仅此一项便会获得更多的见解。正如我最近被告知的那样:拥有好主意的最好方法是拥有许多主意。
G. Bach 2013年

Answers:


7

除了Yuval所说的以外,另一个提示是:它有助于以特定的方式将堆栈放置在阵列中,并相应地确定其增长方向。他们不必朝着同一方向发展。


5

这里有一些提示:

  1. 堆栈之一应“向上”生长,而另一层应“向下”生长。
  2. 无法“记住”哪个元素属于哪个堆栈 -您可以使用其他变量来帮助您进行此类操作。(这对于第一个提示提出的解决方案更有意义。)


1

该方法有效地利用了可用空间。如果arr []中有可用空间,则不会导致溢出。这个想法是从arr []的两个极端角开始两个堆栈。stack1从最左边的元素开始,stack1中的第一个元素被推入索引0。stack2从最右边的角开始,stack2中的第一个元素被推入索引(n-1)。两个堆叠都沿相反的方向生长(或收缩)。为了检查溢出,我们需要检查的是两个堆栈的顶部元素之间的空间。


-1

我想到了另一种解决方案。如果我们将数组拆分为一半(如果数组的长度为奇数,则将数组拆分为尽可能近的数组),并使第一个元素进入第一个堆栈,第二个元素进入第二个堆栈。弹出时,我们可以追溯这些步骤。但是,以这种方式实现会违反任何堆栈原则吗?


ñññ/2

-2

一些提示

制作一个数组

具有奇数索引的数组元素适用于stack1

具有偶数索引的数组元素用于stack2

现在您可以从左向右生长两个堆叠

只要保留保持两个堆栈顶部位置的变量即可。您无需搜索数组。

如果在stack2为空时stack1变满,则可以通过维护一些变量来跟踪stack2中其他stack1元素


这非常令人费解。现有的答案已经提供了解决问题的简单得多的方法
David Richerby
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.