来源:互联网 发布:mac sogo拼音输入法 编辑:程序博客网 时间:2024/06/07 05:48

栈是一种基于后进先出(LIFO)策略的集合类型,当放入数据时,压入(push)最顶端,当取数据时,从顶端弹出(pop)。

stack

栈的基本操作

由此可以定义栈的基本操作:

  1. void push(Item item)
  2. Item pop()
  3. boolean isEmpty()
  4. int size()

以上就是栈支持的所有操作,这是一个严格的接口说明书,没有额外的多余操作,这是一个良好的习惯,仅提供必需的接口,简洁而清晰(有些语言的库函数提供了Stack功能,但是却提供了额外的操作,比如可以在栈顶和栈底添加和删除元素)。

栈的实现

依照上述的接口说明书,我们可以通过各种结构来实现栈,最容易想到的就是上篇文章提到的线性存储结构,数组和链表。

数组实现

构造固定容量的一个数组, 每次在数组的尾部进行添加和删除,当该固定容量数组达到上限,即数组已满,需要扩展数组容量(比如容量翻倍),把原来数据全部搬家到新数组,后续使用新数组继续操作。 随着数据的pop出栈,数据越来越少,数组空闲了很多空间,因此需要处理此种情况,当数据占用比例小于一定的数值,则需要重新申请一个小空间的数组,把数据搬家到此数组,把原来的大数组空间释放。

链表实现

使用前面文章描述的双循环链表,可以方便的实现栈所支持的操作。

初始状态,构造一个双循环链表,仅包含头节点。

  1. void push(Item item)
    从双循环链表的尾部添加节点。

  2. Item pop()
    从双循环链表的尾部删除节点。

  3. boolean isEmpty()
    判断头结点是否指向头结点。

  4. int size()
    内部维护一个计数器,当push时增加1,当pop时,减小1。

依靠双循环链表的通用结构,方便的实现栈,时间和空间复杂度为O(1),简洁而高效。

栈的应用

栈是计算机科学中很重要的一种数据结构。如各种编程语言支持的函数调用过程,均是压栈的过程,函数调用返回就是出栈的过程。 后面将要谈到的递归, 是对栈使用过程的完美诠释。

原创粉丝点击