基本模型就不介绍了,现明确几个规定。

  • 对空栈的Pop和Top一般被认为是栈ADT的错误。
  • 当运行Push时空间用尽是一个实现错误,不是ADT错误。

关于这两者的区别,书上没有说。这里写下我的理解:
ADT是宏观考虑,表明对模型处理的操作,push、pop等等,它指定要做些什么(在空栈情况下做什么?在不空的栈下做什么?),但是不指出怎么做(具体实现)。
所以ADT是从设计架构方面的考虑,实现错误,指的是具体实现有问题。
这两者的界限不是特别明显,论述只是加以区分。
其实,对特殊情况的考虑是编程时应当特别注意的问题,在一些算法中,起到了边界限制(比如dfs等)的作用。

ADT的一些规定

在STL中,在本书中,对于一些常用函数的操作规定是一致的。
比如:

  • pop(s) 将栈顶元素删除,不返回值
  • top(s) 返回栈顶元素。
  • push(s) 插入元素到栈顶,不返回值。

    代码实现

    栈的链表实现.cpp
    这个实现是我自己写的,下面说明几个问题:

  • malloc 申请内存成功与否的判断问题(代码没有实现,具体看书)

在语法中,malloc 申请成功则返回指针,否则返回 null,也就是说即便没有申请成功,也会返回内容且不报错。从异常处理的角度去看,也就是说,将异常与否推给上层程序员处理(也就是我们,包的实现者并没有处理)。所以需要判断malloc申请内存成功与否的问题。
关于判断malloc申请内存是否成功的问题? [问题点数:40分,结帖人Crazy_hand]

  • top和pop

这两者的正常运行需要栈不为空,所以需要先判断栈空与否才能继续下面的运行。
push则不需要这样考虑。

问题分析

注意到在栈的pop和push过程中,有频繁的malloc和free操作,开销较大(时间角度上),所以可以:

Some of this can be avoided by using a second
stack, which is initially empty. When a cell is to be disposed from
the first stack, it is merely placed on the second stack. Then, when
new cells are needed for the first stack, the second stack is checked
first

这是一种空间换时间的办法(内存要求的大一些)

优点

栈的大小不需要事先指定(相比于数组实现的栈,需要事先指定),可以使用所有的内存空间。