栈是什么?

一种先进后出,后进先出的数据结构,只允许在一端插入和删除数据。

数组或链表与栈对比

数组或链表操作灵活自由,但是暴露了太多的操作接口,使用时比较不可控,容易出错。

栈使用受限较多,但是比较可控,不容易出错。

“栈”操作的时间、空间复杂度

不管是 顺序栈(基于数组实现的栈) 还是 链式栈(基于链表实现的栈),我们存储数据只需要一个大小为 n 的数组就够了,在入栈和出栈过程中,只需要一两个临时变量存储空间,所以空间复杂度为 O(1)。

不管是 顺序栈 还是 链式栈,入栈、出栈都只涉及栈顶个别数据的操作,所以时间复杂度为 O(1)。

栈支持动态扩容

链式栈自然不必说,顺序栈也是支持动态扩容的,只需要底层依赖一个支持动态扩容的数组即可。

虽然支持动态扩容的栈在开发中不常用到,但是借用它可以更好地进行栈的复杂度分析。

以入栈操作举个例子,当栈中有空闲空间时,入栈操作的时间复杂度为 O(1);当空间不够使,就需要重新申请内存和数据迁移,所以时间复杂度就变成了 O(n)。

因为大部分情况下,入栈操作的时间复杂度都为 O(1),只有在极端情况下才是  O(n),根据前面所讲的均摊时间复杂度,将耗时多的入栈操作的时间均摊到其他入栈操作上,平均情况下的耗时就接近 O(1),因此栈的时间复杂度为 O(1)。

 实现一个简单的顺序栈

 1 // 基于数组实现的顺序栈
 2 public class ArrayStack {
 3   private String[] items;  // 数组
 4   private int count;       // 栈中元素个数
 5   private int n;           // 栈的大小
 6 
 7   // 初始化数组,申请一个大小为 n 的数组空间
 8   public ArrayStack(int n) {
 9     this.items = new String[n];
10     this.n = n;
11     this.count = 0;
12   }
13 
14   // 入栈操作
15   public boolean push(String item) {
16     // 数组空间不够了,直接返回 false,入栈失败。
17     if (count == n) {
18         return false;
19     }
20     // 将 item 放到下标为 count 的位置,并且 count 加一
21     items[count] = item;
22     ++count;
23     return true;
24   }
25   
26   // 出栈操作
27   public String pop() {
28     // 栈为空,则直接返回 null
29     if (count == 0) {
30         return null;
31     }
32     // 返回下标为 count-1 的数组元素,并且栈中元素个数 count 减一
33     String tmp = items[count-1];
34     --count;
35     return tmp;
36   }
37 }

内容小结

  • 栈是一种操作受限的数据结构,只支持入栈和出栈操作。
  • 栈最大的特点是后进先出。
  • 栈既可以通过数组实现,也可以通过链表实现。
  • 不管是数组还是链表,入栈、出栈的时间复杂度都是 O(1)。

 

    原文作者:hardyyao
    原文地址: https://www.cnblogs.com/hardyyao/p/9763077.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞