欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

左神初级班03

程序员文章站 2024-02-01 08:55:16
...

数组结构实现固定的队列和栈

1 栈
新建数组(固定长度)、index指针
index指针指向新加数的位置

基本操作:
1、push压栈:先检查栈是否已满,报异常;否则压栈,index++
2、peek弹出栈顶元素但不删除:检查栈是否已满,弹出的是index - 1(注意index指向的元素含义)
3、 pop弹出栈顶元素并删除:检查栈是否已满,return栈顶元素,–index

代码实现

public class ArrayStack {
    public int[] arr;
    public int index;

    //1 设置一个固定数组大小initSize,初始化数组arr
    public ArrayStack(int initSize){
        if(initSize < 0){
            throw new IllegalArgumentException("The init Size is less than 0");//不合法的参数异常
        }
        arr = new int[initSize];
        index = 0;
    }

    //2 栈操作:peek\push\pop
    public void push(int obj){//压栈
        if(index == arr.length){
            throw new ArrayIndexOutOfBoundsException("The queue is full");//数组越界
        }
        obj = arr[index++];
    }

    public int pop(){//弹栈顶
        if(index == 0){
            throw new ArrayIndexOutOfBoundsException("The queue is empty");
        }
        return arr[--index];
    }

    public Integer peek(){
        if(index == 0){
            return null;
        }
        return arr[index - 1];
    }
}

2 队列(难度+)
新建数组(固定长度);两个指针:start、end;队列中个数size
两指针start和end之间是独立的,无约束关系,end和start一开始均指向0位置。
end变量代表新加一个数应该把它填到什么位置上,start变量代表用户拿一个数时应该拿哪个数。

size与两指针之间分别有约束关系:
1、size < length:将新数放到end位置上,size++,end++
2、size != 0:将start指的数返回给用户,size–,start++
3、end/start只要到底了,就回到开头,start在不断的追end,是一个循环
基本操作: peek、push、poll(同上)

代码实现

public class ArrayQueue {
    //1 初始化
    public int[] arr;
    public int size;
    public int start;
    public int end;

    public ArrayQueue(int initSize){
        if(initSize < 0){
            throw new IllegalArgumentException("The init size is less than 0");
        }
        arr = new int[initSize];
        size = 0;
        start = 0;
        end = 0;
    }
    //2 基本操作
    public Integer peek(){
        if(size == 0){
            return null;
        }
        return arr[start];
    }

    public void push(int obj){
        if(size == arr.length){
            throw new ArrayIndexOutOfBoundsException("The queue is full");
        }
        size++;
        obj = arr[end];
        end = end == arr.length - 1 ? 0 : end + 1;//如果end指针到底了就返回头部0位置,否则 + 1
    }

    public int poll(){
        if(size == 0){
            throw new ArrayIndexOutOfBoundsException("The queue is empty");
        }
        size--;
        int temp = start;
        start = start == arr.length - 1 ? 0 : start + 1;
        return arr[temp];
    }

实现特殊的栈,并返回栈中最小元素(比较著名的题)

实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作。
要求:1、pop、push、getMin操作的时间复杂度O(1);2、设计的栈类型可以使用现成的栈结构

思路
使用两个栈结构data栈和min栈,两个栈元素一起增长,分别存放数据和当前最小值。设要压入元素num,若num < data栈栈顶,则两个栈同时压入num;若num > data栈栈顶,则data栈压入num,min栈压入min栈的最小值(重复压入),则需要返回时去min栈栈顶即可。
增加空间,维持最小值。

代码实现

public static class MyStack2{
        private Stack<Integer> stackData;
        private Stack<Integer> stackMin;


        public MyStack2(){
            this.stackData = new Stack<Integer>();
            this.stackMin = new Stack<Integer>();
        }
        //基本操作
        //压栈
        public void push(int newNum){
            if(this.stackMin.isEmpty()){
                this.stackMin.push(newNum);
            }else if(newNum < this.getmin()){
                this.stackMin.push(newNum);
            }else {
                int newMin = this.stackMin.peek();
                this.stackMin.push(newMin);
            }
            this.stackData.push(newNum);
        }
        //弹出
        public int pop(){
            if(this.stackMin.isEmpty()){
                throw new RuntimeException("The stack is empty");//该异常在下面详细阐述
            }
            this.stackMin.pop();
            return this.stackData.pop();
        }

        //获取stackMin栈中栈顶元素
        public int getmin(){
            if(this.stackMin.isEmpty()){
                throw new RuntimeException("The stack is empty");
            }
            return this.stackMin.peek();
        }
    }

补充知识点
Exception 和 RuntimeException的区别:
左神初级班03
1、其他Exception,受检查异常。
可以理解为错误,必须要开发者解决以后才能编译通过,解决的方法有两种:1.throw到上层 2.try-catch处理。
2、RunTimeException:运行时异常,又称不受检查异常,不受检查!
因为不受检查,所以在代码中可能会有RunTimeException时Java编译检查时不会告诉你有这个异常,但是在实际运行代码时则会暴露出来,比如经典的1/0,空指针等。如果不处理也会被Java自己处理。


如何用队列实现栈,用栈实现队列

适用范围举例:面试官提问使用队列结构来进行图的深度优先遍历?将队列转化为栈进行遍历

1 用队列实现栈
思路
用两个队列实现栈,两个队列data和help,data中装栈读入的数据,help中装不弹出的数据。
举个简单例子,栈中装入数据[1,2,3,4,5],根据先入后出,应弹出5,则data队列中装入[1,2,3,4,5],help队列从data队列弹出并装入[1,2,3,4],留最后一个数返回,data队列弹出数据,并将data和help队列互换。

代码实现

public static class TwoQueuesStack{
        private Queue<Integer> data;
        private Queue<Integer> help;

        public TwoQueuesStack(){
            data = new LinkedList<Integer>();//LinkedList双向链表
            help = new LinkedList<Integer>();
        }
        //入栈
        public void push(int pushInt){
            data.add(pushInt);
        }
        //读栈顶
        public int peek(){
            if(data.isEmpty()){
                throw new RuntimeException("Stack is empty");
            }
            while(data.size() > 1){
                help.add(data.poll());//pop的安全方法
            }
            int res = data.poll();
            help.add(res);//因为是peek,不改变栈内数据
            swap();
            return res;
        }
        //弹栈顶并删除
        public int pop(){
            if(data.isEmpty()){
                throw new RuntimeException("Stack is empty");
            }
            while(data.size() > 1){
                help.add(data.poll());
            }
            int res = data.poll();
            swap();
            return 0;
        }

        public void swap(){
            Queue<Integer> tmp = help;
            help = data;
            data = tmp;
        }      
    }

2 用栈实现队列
思路
用两个栈实现队列,初始化两个栈:push栈和pop栈。push栈压入队列中的数,pop栈用来存放push栈中pop出来的数。弹出pop栈中的元素,即队列顺序。

实现过程中必须要满足的两个原则:
1、push栈只要倒出,必须一次性倒完,否则pop栈从弹出的第一个元素开始顺序错误
2、pop栈中有数据时,push栈中不可以进行倒出操作,否则pop栈顺序错误

代码实现

public static class TwoStacksQueue{
        private Stack<Integer> stackPush;
        private Stack<Integer> stackPop;

        public TwoStacksQueue(){
            stackPush = new Stack<Integer>();
            stackPop = new Stack<Integer>();
        }

        //入队列
        public void push(int pushInt){
            stackPush.push(pushInt);
        }

        //出队列
        public int poll(){
            if(stackPush.isEmpty()&&stackPop.isEmpty()){
                throw new RuntimeException("Queue is empty");
            }else if(stackPop.isEmpty()){
                while (!stackPush.isEmpty()){
                    stackPop.push(stackPush.pop());
                }

            }
            return stackPop.pop();
        }
        //出队列,不删除
        public int peek(){
            if(stackPush.isEmpty() && stackPop.isEmpty()){
                throw new RuntimeException("Stack is empty");
            }else if(stackPop.isEmpty()){
                stackPop.push(stackPush.pop());
            }
            return stackPop.peek();
        }
    }

上一篇: 1. 了解HTML

下一篇: