zoukankan      html  css  js  c++  java
  • 用数组实现栈

    用数组表示栈

    选择用数组表示栈内容必须预先估计栈的最大容量。在Java中,数组一旦创建,其大小是无法改变的,而数组设置过大可能会浪费大量内存,设置过小又可能会溢出。

    所以我们希望能够动态调整数组a[i]的大小,使得它既足以保存所有元素,又不至于浪费过多的空间。

    首先,实现一个方法将栈移动到另一个大小不同的数组中。

    1 private void resize(int max) {
    2         
    3         Item[] temp = (Item[]) new Object[max];
    4         for (int i = 0; i < N; i++) {
    5             temp[i] = a[i];
    6         }
    7         a = temp;
    8     }

     然后在push()中检测数组是否太小。如果没有多余的空间,就将数组的长度加倍。

    1  public void push(Item item) {
    2 
    3         if (N == a.length) resize(2*a.length);    
    4         a[N++] = item;                         
    5 
    6     }

    类似的,在pop()中,先删除栈顶元素,然后如果栈大小小于数组的四分之一就将数组的长度减半(这样数组长度被减半之后约为半满,在下次需要改变数组大小之前仍然能够进行多次push()和pop()操作)。

    1  public Item pop() {
    2         
    3         Item item = a[--N];
    4         a[N] = null;                              //避免对象游离(见标注)
    5        
    6         if (N > 0 && N == a.length/4) resize(a.length/2);
    7         return item;
    8     }

     注:在对pop()的实现中,被弹出的元素的引用仍然存在于数组中。它永远不会再被访问了,但Java的垃圾回收集器无法知道这一点,除非该引用被覆盖。这种情况(保存一个不需要的对象的引用)称为游离。

    在这里,只需将被弹出的数组元素的值设置为null即可。

     下面给出用数组表示栈的代码实现:

       下压(LIFO)栈(能够动态调整数组大小的实现):

     1 public class ResizingArrayStack<Item> implements Iterable<Item> {
     2     private Item[] a;        
     3     private int N;           
     4 
     5     public ResizingArrayStack() {
     6         a = (Item[]) new Object[2];
     7         N = 0;
     8     }
     9 
    10 
    11     public boolean isEmpty() {
    12         return N == 0;
    13     }
    14 
    15 
    16     public int size() {
    17         return N;
    18     }
    19 
    20 
    21     private void resize(int capacity) {
    22         assert capacity >= N;
    23         Item[] temp = (Item[]) new Object[capacity];
    24         for (int i = 0; i < N; i++) {
    25             temp[i] = a[i];
    26         }
    27         a = temp;
    28     }
    29 
    30 
    31     public void push(Item item) {
    32         if (N == a.length) resize(2*a.length);    
    33         a[N++] = item;                            
    34     }
    35 
    36     public Item pop() {
    37         Item item = a[--N];
    38         a[N] = null;                              
    39 
    40         if (N > 0 && N == a.length/4) resize(a.length/2);
    41         return item;
    42     }
    43 
    44 
    45     public Item peek() {
    46         return a[--N];
    47     }
    48 
    49 
    50     public Iterator<Item> iterator() {
    51         return new ReverseArrayIterator();
    52     }
    53 
    54     private class ReverseArrayIterator implements Iterator<Item> {
    55         private int i;
    56 
    57         public ReverseArrayIterator() {
    58             i = N;
    59         }
    60 
    61         public boolean hasNext() {
    62             return i >= 0;
    63         }
    64 
    65         public void remove() {
    66             throw new UnsupportedOperationException();
    67         }
    68 
    69         public Item next() {
    70             return a[--i];
    71         }
    72     }
    73 
    74 }

    用数组表示栈的优点:

          每项操作的用时都与集合大小无关;

          空间需求总是不超过集合大小乘以一个常数。

    用数组表示栈的缺点:

          某些push()和pop()操作会调整数组的大小:这项操作的耗时和栈大小成正比。

  • 相关阅读:
    Netty实战
    ObjectTools反射实例
    SpringBoot新增监听器Listener
    拦截器(Inteceptor),过滤器(Filter),切面(Aspect)处理HttpServiceReqeust请求
    Linux CentOS7.2下安装Redis && 配置Redis开机自启动
    JVM命令行工具&垃圾收集器&垃圾收集策略思维导图
    Redis总结
    Java自定义注解的实现
    反射实例
    系统管理员常用的Linux命令
  • 原文地址:https://www.cnblogs.com/CZDblog/p/5576131.html
Copyright © 2011-2022 走看看