用C ++编写的堆栈。他们为何以及何时使用?

时间:2014-10-03 21:06:54

标签: c++ stack

阅读有关堆栈的章节(第7章,使用C ++的数据结构。第2版,D.S。Malik)。我似乎很难理解在C ++中使用堆栈的概念。

我理解堆栈本身是一种数据类型,主要用于LIFO(后进先出)编程风格。堆栈可以提供使用的功能......例如poppushisEmptyisFulltop,但我不会非常了解每个人完全做了什么,以及他们如何一起工作。

他们在“大局”中使用了什么?我怎么能想到堆栈在编写代码时有用呢?

任何解释或示例都会非常有用!

谢谢,

5 个答案:

答案 0 :(得分:2)

堆栈用于各种算法。一些例子:

  • 在迭代等价物中翻译递归算法
  • parralelizing递归算法(需要线程安全的堆栈实现)
  • 实现深度优先图搜索,当具有队列的相同算法将首先给您呼吸时。
  • 执行后缀表达式
  • 等...

关于堆栈的一般原则:

  • 在开始时,堆栈为空。通常需要检查堆栈是否为空,以了解htere是否是要处理的其他元素。
  • 固定大小的堆栈实现需要在尝试存储新元素之前检查空间是否仍然空闲。
  • push 将新元素放在堆栈顶部,从而增加了元素数量。
  • pop 从堆栈顶部获取元素(即最后一个被推送的元素)并减少堆栈。
  • 顶部读取堆栈的顶部元素,但将其保留在原始位置而不修改堆栈。

关于top和pop的注释:在传统堆栈中(例如:CPU的汇编程序),pop会读取堆栈的顶部并将其删除。但是许多实现将顶部的两个操作(读取顶部元素)和pop(删除顶部元素)分开。

我建议你熟悉std::stack,这与你的书略有不同(至少对于操作的命名)但是立即可用。

答案 1 :(得分:2)

我刚检查了我的代码库,我使用类似堆栈的数据结构的唯一地方是:

  1. 解析脚本的lexing阶段,匹配括号的位置,仅用于更好的错误消息。
  2. 在评估脚本期间,如果我需要在脚本完成之前返回(即在“睡眠”调用期间,以便其他代码仍然可以运行),我可以保存“环境”。
  3. 我更常见的是使用递归调用(即硬件堆栈),或者想要一个集合或队列。

答案 2 :(得分:0)

在许多特定情况下,您可能希望使用堆栈。想到的是

  1. 转换"正常"将数学表达式中缀为后缀或前缀表达式。

  2. 评估数学表达式。

  3. 穿越迷宫。

答案 3 :(得分:0)

我在编译器中使用堆栈来跟踪每个"范围"中的局部变量和类型。 - 因为它是一个Pascal编译器,它允许嵌套函数,并在每个嵌套级别使用一组新的变量和类型。所以,我有一个堆栈,它以全局变量开头,然后对于每个级别的函数,我添加另一个级别的堆栈。当功能完成"完成"时,堆栈被弹出"删除该图层。

堆栈用于许多其他类似的东西,换句话说,你有层的东西。你可以分解数学表达式:

 x = a + b * (d - e); 

所以,我们找到了x =,看看下一步是什么:它不仅仅是一个变量,所以我们必须把它分成几部分:

 a + b, 

但接下来是*,其优先级高于+,因此我们需要推送我们拥有的a+b远远到堆栈,并首先计算*的东西。这是括号,所以我们也必须推*,并计算d - e。现在我们可以开始向堆栈的底部走去:pop给我们*然后b,然后将它们相乘,然后弹出下一个,这会给+a。最后,我们得到=x,因此我们进行了分配。 (虽然在我的编译器项目中,我只是通过从二元运算符解析器中调用二元运算符解析器来解决这个问题)。

许多游戏尝试不同的选择" (数独求解器,国际象棋,Tic-Tac-Toe,迷宫发现等)使用递归或堆栈来跟踪"我们有什么选项",其中每个进一步的移动是堆栈上的另一层。同样,它可以在常规递归中完成,也可以使用堆栈完成。只需列举可能的"移动"在这一点上,选择一个并进行移动,然后为对手做同样的事情[假设它是一个双向游戏,而不是数独游戏或迷宫],依此类推。每个"播放步骤"是一个堆栈级别。如果你找到一个好的"一,存储后回溯#34;这是正确的举动" - 如果它变得很糟糕,那么就回过头来看看"不是一个好的举动" [在国际象棋中,例如,许多动作可能是"好的" (因为有几种选择,或者因为有很多选择我们不能一直尝试每一个人来赢得/失败"情况)和一些"坏&#34 ,那么你必须得分,"有多好"它是]。

还有很多其他事情需要记住我之前的位置,以便我以后可以回复它#34;

答案 4 :(得分:0)

编辑:在我原来的回答中,我愚蠢地忽略了现有的STL 堆栈实现,std::stack。这有pushpoptop个函数 这完全符合您的期望,以及实现该功能的empty函数 期望的isEmpty()功能。

例如,要使my_stack_instance成为一堆整数,您可以简单地完成 声明

std::stack<int> my_stack_instance;

没有&#34; isFull&#34;操作本身。 std::stack应该&#34;成长&#34; (如果超出其容量,则在更大的内存块中重新分配)。

我之前的建议是使用std::vector。理想情况下,它不会 你的 堆栈对象,它将是 in 您的堆栈对象,以便您可以公开函数 使用有意义的名称,而不是暴露你不想要的功能。 如果您使用std::stack,那么它也可能 您的堆栈对象 已经完全暴露了它应该的功能。

如果你必须实现一个堆栈,以证明你理解一个类, 然后std::stack可能不会被接受。然后我会挑选一根骨头 与您的导师一起使用C ++作为教学&#34;语言,但是 我想这是一个不同的主题。