Java栈和队列的基础实验操作

一、括号匹配问题

本题主要是有关括号顺序类的题,有关顺序的题都可以考虑用栈来做。

思路:遍历存储括号们的字符串,新出现的右括号一定与最新入栈的左括号匹配,所以当碰见左括号就进行入栈操作,当出现右括号进行出栈操作即可。

class Solution {
    public boolean isValid(String s) {
        Stack<Character> stack = new Stack<>();
        for (int i = 0; i < s.length() ; i++) {
            char ch = s.charAt(i);
            if(ch == '{' || ch == '[' || ch == '(' ){ //为左括号时入栈
                stack.push(ch);
            }else {    
                if(stack.empty()){  //当栈空但字符串出现右括号 说明不匹配
                    return false;
                }
              char ch2 = stack.peek();  //获取栈顶左括号
              if(ch2 == '{' && ch == '}' || ch2 == '[' && ch == ']' || ch2 == '(' && ch == ')' ){ 
                stack.pop(); //当左右括号匹配时 出栈
              } else{
                return false; //不匹配时 return
              }
                 
            }

        }
        return stack.empty()? true : false; //当字符串遍历完而栈内还有元素则说明不匹配
    }
}

不匹配的情况:

1.当栈为空但遍历到右括号时 false

2.当右括号与新入栈的左括号不匹配时 false

3.当字符串遍历完但栈不为空 false

二、逆波兰表达式求值

当给出一段字符串求逆波兰表达式,思路:遍历字符串,为数字时入栈,为符号时出栈两个数字,先出栈的放在符号右边,计算完成后入栈,重复操作。

class Solution {
    public int evalRPN(String[] tokens) {
        Stack<Integer> stack = new Stack<>(); 
   //因为栈内存储的一定为数字 所以创建Integer泛型栈
        for(int i = 0;i < tokens.length;i ++){ 遍历字符串tokens
            String str = tokens[i];
            if( !Operation(str)){ 如果不是操作符
                int val = Integer.valueof(str); //将str转换为int类型后入栈
                stack.push(val);
            }else{ //当不是数字时
                int num1 = stack.pop(); //出栈两个数字
                int num2 = stack.pop();
                switch(str){ //因为分为四种情况,使用switch便于操作
                    case "+":
                    stack.push(num2 + num1);
                    break;
                    case "-":
                    stack.push(num2 - num1);
                    break;
                    case "*":
                    stack.push(num2 * num1);
                    break;
                    case "/":
                    stack.push(num2 / num1);
                    break;
                }
            }
        }
        return stack.pop(); //遍历完字符串 此时栈内的元素则为结果

    }

    public boolean Operation(String str){ //判断是否为操作符
        if(str.equals('-') || str.equals('+') || str.equals('*') || str.equals('/')){
            return true;
        }
        return false;
    }
}

1.栈内存储的一定为数字 所以创建Integer泛型栈

2.当遍历的不是操作符,转换为int类型后入栈

3.四种操作符所以有四种情况,依次列举即可

整体来说不算很难,知道思路后慢慢写就好。

三、判断第二个数组是否为第一个数组的压入弹出序列

因为栈是先进后出的单向列表,经常会有判断一个数组是否为另一个数组的合法弹出序列的题目,通过本题可以透彻学会此类题型。

思路:遍历两个数组,首先遍历push数组然后与pop数组计数器j位置的元素比较,如果相同就出栈,计数器向后移动。不同就入栈直到碰到相同元素。

public boolean IsPopOrder (int[] pushV, int[] popV) {

        Stack<Intager> stack = new Stack<>(); //创建Integer泛型栈

        int j = 0; //j为遍历popV数组的计数器

        for(int i = 0;i < pushV.length;i++){  //首先遍历push数组

            if(pushV[i] != popV[j] && j < popV.length ){//当碰见与pop数组不相同的元素就入栈

                stack.push(pushV[i]);

            }else{ //相同则出栈

                stack.pop();

                j++; //j移到pop数组下一位置

            }

        }
         //当pop数组未遍历完成,但栈已经为空,则说明不符合,return false

        if(j <= popV.length || !stack.isEmpty()){

              return false;

        }

        return true;

    }

} 

1.需要注意j的值不能超过数组长度,否则会出现栈溢出现象

2.当pop数组未遍历完成,但栈已经为空,则说明不符合

四、获取栈中最小值

思路:栈只能进行单向操作先入后出,要想获得栈中的最小值需要建一个新栈来存储最小值。最小值栈入栈时应该进行判断,如果小于栈顶的元素才可以入栈,入栈后此元素就为最小值,这样的话将最小值栈出栈一个元素后栈顶的元素就是新的最小值。

public MinStack() {
    stack = new Stack<>(); //普通栈
    minstack = new Stack<>(); //最小值栈
}

public void push(int val) {
    stack.push(val); //普通栈直接入栈元素
    if(minstack.isEmpty()){ //先判断最小值栈是否为空
        minstack.push(val); //为空则入栈
        return;
    }
    if(minstack.peek() <= val){ //判断元素与栈顶的大小
        stack.push(val);
        return;
    }else{
        return;
    }
}

public void pop() {
    int num = stack.pop();
    if(num == minstack.peek()){ //如果普通栈出栈的元素与最小值栈顶元素相同
        minstack.pop(); //则最小值也出栈
    }
}

public int top() {
    return stack.peek(); //获取栈顶元素
}

public int getMin() {
      return minstack.peek(); //获取最小值
}

1.当最小值栈为空时直接压入元素

2.当普通栈出栈一个与最小值栈相同的元素,最小值栈也应该出栈,否则会出现最小值是一个不存在的数字 

3.如果新的元素与最小值栈的相同也需入栈,否则普通栈有两个这个数,当出栈一个后最小值栈也会把这个数出栈,如果这个数为最小值的话那就会出现数据丢失。

五、设计循环队列

思路:设置front,rare,usedsize为成员变量

    int[] elem; //为初始队列
    int front; //头部
    int rare; //尾部
    int usedSize; //实际占用元素

1.构造方法:将数组初始化为给定的形参大小

public MyCircularQueue(int k) {
        elem = new int[k];
    }

2.Front 获取头部元素 直接return头部下标元素

 public int Front() {

        if(isEmpty()){ //当栈空返回-1

            return -1;
        }

        return elem[front];

    }

3.Rear获取队尾元素

public int Rear() {

         if(isEmpty()){

            return -1;

        }

        return elem[(rare-1 + elem.length) % elem.length];

    }

4.插入元素 

public boolean enQueue(int value) {

        if(isFull()){

            return false;

        }

        elem[rare] = value;
        rare ++;
        if(rare == elem.length){
            rare = 0;
        }
        usedSize ++;
        

        return true;

    }

5.删除元素,在头部删除元素时,front可能会在尾部的位置,直接front++会栈溢出,借助下面公式就能帮助回到初始位置。

 public boolean deQueue() {

        if(isEmpty()){

            return false;

        }

        front ++;

       front = (front+elem.length) % elem.length;
       usedSize --;

        return true;

    }

6.判断队列为空还是满,直接借助usedSize就能获得

public boolean isEmpty() {

        return usedSize == 0;
    }

    

    public boolean isFull() {

        return usedSize == elem.length;

    }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值