【算法学习系列】Java语言栈和队列的操作

关于栈和队列的基础知识这里不再赘述,具体可以参照数据结构教材,但只需要记住两者的特性:栈——先进后出,队列:先进先出。

1 使用数组实现固定大小的栈和队列结构

1.1 使用数组构建栈结构

这里实现进栈出栈和取栈顶元素三个方法

//数组栈
    public class ArrayStack{
        private Integer[] arr;
        private Integer index;
        public ArrayStack(int initSize){
            if(initSize<0){
                throw new IllegalArgumentException("the size is less than 0");
            }
            arr=new Integer[initSize];
            index=0;
        }
        //获取栈顶元素
        public Integer top(){
            if(index==0){
                return null;
            }
            return arr[index-1];
        }
        //进栈
        public void push(int ele){
            if(index==arr.length){
                throw new ArrayIndexOutOfBoundsException("has no space to store data");
            }
            //先放元素 再++
            arr[index++]=ele;
        }
        //出栈
         public Integer pop(){
            if(index<=0){
                throw new ArrayIndexOutOfBoundsException("no element can be given");
            }
            //先-- 再放元素
            return arr[--index];
         }
    }
1.2 使用数组构建队列结构

这里实现入队出队和取栈顶元素三个方法,其中借助了Size进行约束限制队列中元素的数目

//数组队列
    public static class ArrayQueue{
        private int size;
        private int start;
        private int end;
        private Integer arr[];
        public ArrayQueue(int initSize){
            if(size<0){
                throw new IllegalArgumentException("the size is less than 0");
            }
            arr=new Integer[initSize];
            start=end=size=0;
        }
        //入队
        public void inQueue(int ele){
            if(size==arr.length){
                throw new ArrayIndexOutOfBoundsException("index outBound");
            }
            size++;
            arr[end]=ele;
            end=nextIndex(arr.length,end);
        }
        //出队
        public Integer outQueue(){
            if(size==0){
                throw new ArrayIndexOutOfBoundsException("Queue is empty");
            }
            size--;
            Integer result=arr[start];
            start=nextIndex(arr.length,start);
            return result;
        }
        //得到进出队列限一次操作的索引值
        public int nextIndex(int size,int index){
            return index==size-1 ? 0 : index+1;
        }
        //得到队首元素
        public Integer peek(){
            if(size==0){
                throw new ArrayIndexOutOfBoundsException("Queue is empty");
            }
            return arr[start];
        }
    }

1.3 在Java内部也实现了Stack类,具体可以参考一下Java API,在写一些算法题目的时候,可以直接调用相关的API实现。下面结合一道题目来描述下Java内部Stack的使用。

用栈实现出栈入栈和取最小值的时间复杂度为O(1)
算法分析:这里其实我们的出栈和入栈本身就是O(1),但是在求取最小值的时候,需要考虑使用双栈结构实现,一个是只存储数据的栈,另一个是只存储每次当前最小值的栈结构,假设入栈序列为(10,7,6,3,8,9),其算法原理如下图所示:

在这里插入图片描述
在这里插入图片描述
上图步骤为,每次将序列中的数字进入数据栈,在最小栈中栈顶存储的是当前数据战中的最小址,这样在取数据栈内元素最小值时,可以直接获取栈顶元素即位最小值,保证了时间复杂度是1,在数据栈中元素进行弹出时,最小值栈也跟着弹出元素。当然这种实现,是两种栈都使用了相同的空间数目。

代码如下:
 //栈结构实现进出栈以及获取最小值的时间复杂度为O(1)
    //思想是使用两个栈
    public class OptimizeStack{
        private Stack<Integer> dataStack;
        private Stack<Integer> minStack;
        public OptimizeStack(){
            this.dataStack=new Stack<Integer>();
            this.minStack=new Stack<Integer>();
        }
        //进栈
        public void push(int ele){
            if(this.minStack.isEmpty()){
                this.minStack.push(ele);
            }else if(ele>this.minStack.peek()){
                this.minStack.push(this.minStack.peek());
                this.dataStack.push(ele);
            }else{
                this.minStack.push(ele);
                this.dataStack.push(ele);
            }
        }
        //得到最小值
        public Integer getMin(){
            if(this.minStack.isEmpty()){
                throw new NullPointerException("no data in stack");
            }
            return this.minStack.peek();
        }
        //出栈
        public Integer pop(){
            if(this.dataStack.isEmpty()){
                throw new NullPointerException("no data in stack");
            }
            this.minStack.pop();//从最小栈中弹出
            return this.dataStack.pop();//从数据栈中弹出
        }
    }

当考虑节约空间时,数据栈的大小和序列数是一样的,但是最小栈可以只保存最小值,即碰到比最小栈顶小的数据再入到最小栈中,如下图:
在这里插入图片描述
在这里插入图片描述

代码实现如下:
public static class OptimizeStack{
        private Stack<Integer> dataStack;
        private Stack<Integer> minStack;
        public OptimizeStack(){
            this.dataStack=new Stack<Integer>();
            this.minStack=new Stack<Integer>();
        }
        //进栈
        public void push(int ele){
            if(this.minStack.isEmpty()){
                this.minStack.push(ele);
            }else if(ele>this.minStack.peek()){
                //this.minStack.push(this.minStack.peek());
                this.dataStack.push(ele);
            }else{
                this.minStack.push(ele);
                this.dataStack.push(ele);
            }
        }
        //得到最小值
        public Integer getMin(){
            if(this.minStack.isEmpty()){
                throw new NullPointerException("no data in stack");
            }
            return this.minStack.peek();
        }
        //出栈
        public Integer pop(){
            if(this.dataStack.isEmpty()){
                throw new NullPointerException("no data in stack");
            }
            if(this.dataStack.peek()==this.minStack.peek()){
                this.minStack.pop();//从最小栈中弹出
            }
            return this.dataStack.pop();//从数据栈中弹出
        }
    }

注意比较以上的不同,其实很简单的操作。
有问题欢迎指正!!!!!
【未完待续。。。。】

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值