zoukankan      html  css  js  c++  java
  • 栈的基本操作

    栈是一种基于后进先出(LIFO)策略的集合类型,例如上网点击超链接浏览器会跳到另一个页面(将它压入栈中),点击后退可以回到以前的页面(从栈中弹出),栈的后进先出策略正好提供了这种所需要的行为.当遍历栈中的元素时,元素的处理顺序和它们被压入的顺序正好相反.

    定容栈

    实现起来比较简单,它指定了栈的容量大小,当N=0时栈为空,栈的顶部位于a[N-1],当栈满时插入元素栈会上溢.

    public class FixedCapacityStackOfStrings implements Iterable<String> {
        private String[] a;  // holds the items
        private int N;       // number of items in stack
    
        // create an empty stack with given capacity
        public FixedCapacityStackOfStrings(int capacity) {
            a = new String[capacity];
            N = 0;
        }
    
        public boolean isEmpty()            {  return N == 0;                    }
        public boolean isFull()             {  return N == a.length;             }
        public void push(String item)       {  a[N++] = item;                    }
        public String pop()                 {  return a[--N];                    }
        public String peek()                {  return a[N-1];                    }
        public Iterator<String> iterator()  { return new ReverseArrayIterator(); }
    
    
        public class ReverseArrayIterator implements Iterator<String> {
            private int i = N-1;
    
            public boolean hasNext() {
                return i >= 0;
            }
    
            public String next() { 
                if (!hasNext()) throw new NoSuchElementException();
                return a[i--];
            }
    
            public void remove() {
                throw new UnsupportedOperationException();
            }
        }
    
    
        public static void main(String[] args) {
            int max = Integer.parseInt(args[0]);
            FixedCapacityStackOfStrings stack = new FixedCapacityStackOfStrings(max);
            while (!StdIn.isEmpty()) {
                String item = StdIn.readString();
                if (!item.equals("-")) stack.push(item); 
                else if (stack.isEmpty())  StdOut.println("BAD INPUT"); 
                else                       StdOut.print(stack.pop() + " ");
            }
            StdOut.println();
    
            // print what's left on the stack
            StdOut.print("Left on stack: ");
            for (String s : stack) {
                StdOut.print(s + " ");
            }
            StdOut.println();
        } 
    } 
    View Code

    能够动态调整数组大小的实现

    我们修改数组的实现,动态调整a[]的大小,使得它即足以保存所有元素,又不至于浪费过多空间.

    1.在push()操作中,检查数组的大小.具体说就是检查栈大小N和数组长度a.length是否相等,如果相等则判断没有多余空间,此时将数组大小加倍,然后可以像以前一样用 a[N++] = item 进行插入操作了.

    2.在pop()操作中,首先删除栈顶元素,如果数组太大我们就将它长度减半,检测条件是栈的大小是否小于数组的四分之一(因为数组长度减半之后,它的状态约为半满,在下次需要改变数组大小之前仍能进行多次push()和pop()操作).

    在这个实现中,栈永远不会溢出,使用率也不会低于四分之一(除非栈空,这是数组大小为1).

    java的垃圾回收策略是回收所有无法访问的内存,在pop()实现中,被弹出的元素仍然存在于数组中,这个元素不会再被访问,但java的垃圾收集器不知道这一点,除非引用被覆盖,这种情况称为游离.要避免对象游离很简单,只要把被弹出的数组元素值设为null. 

    import java.util.Iterator;
    
    public class ResizingArrayStack<Item> implements Iterable<Item> {
    
        private Item[] a = (Item[]) new Object[1];    //栈元素
        private int N = 0;        //元素数量
        //判断栈是否为空
        private boolean isEmpty(){ return N == 0; }
        //获取栈大小
        public int size(){ return N;}
        //调整栈大小,将栈元素移动到一个大小为max的数组中
        private void resize(int max){
            Item[] temp = (Item[]) new Object[max];
            for(int i = 0; i < N; i++){
                temp[i] = a[i];
            }
            a = temp;
        }
        public void push(Item item){
            //入栈
            if( N == a.length) resize(2*a.length);
            a[N++] = item;
        }
        public Item pop(){
            Item item = a[--N];
            a[N] = null;    //避免对象游离
            if(N>0 && N == a.length/4) resize(a.length/2);
            return item;
        }
        
        //实现迭代器
        public Iterator<Item> iterator(){
            return new ReverseArrayIterator();
        }
        
        //支持后进先出的迭代
        private class ReverseArrayIterator implements Iterator<Item>{
            private int i = N;
            public boolean hasNext(){
                return i > 0;
            }
            public Item next(){
                return a[--i];
            }
            public void remove(){}
        }
    }
    View Code
     
    性能:每项操作用时都与集合大小无关,空间需求总是不超过集合大小乘以一个常数. 缺点在于某些push()和pop()会调整数组的大小,这项操作耗时和栈大小成正比.
     
     
     
    链表实现
    所需空间总是和集合大小成正比.
    操作所需时间总是和集合大小无关.
     
    public class Stack<Item>{
        
        private Node first;    //栈顶
        private int N;    //元素数量
        //节点定义
        private class Node{
            Item item;
            Node next;
        }
        public boolean isEmpty(){ return first == null ;}
        public int size(){ return N;}
        //入栈
        public void push(Item item){
            Node oldfirst = first;
            first = new Node();
            first.item = item;
            first.next = oldfirst;
            N++;
        }
        //出栈
        public Item pop(){
            Item item = first.item;
            first = first.next;
            N--;
            return item;
        }      
    }
    View Code
     
     
  • 相关阅读:
    为方便储户,某银行拟开发计算机储蓄系统。储户填写的存款单或取款单由业务员输入系统,如果是存款,系统记录存款人姓名、住址、存款类型、存款日期、利率等信息,并印出存款单给储户;如果是取款,系统计算利息并印出利息清单给储户。 写出问题定义并分析系统的可行性。
    “中文编程”是解决中国程序员编程的有效武器,请问它是个“银弹”吗?
    这是我第一个博客
    jupyter-notebook打不开浏览器的问题
    python购物车程序
    python 登陆小程序
    mysql备份恢复(二)
    mysql备份恢复(一)
    docker实践之创建支持ssh服务的镜像
    基于python的设计模式之创建型模型
  • 原文地址:https://www.cnblogs.com/tanxing/p/4921931.html
Copyright © 2011-2022 走看看