Java实现循环队列/栈——先入先出/后入先出的数据结构

先入先出的数据结构

在 FIFO 数据结构中,将首先处理添加到队列中的第一个元素
在这里插入图片描述
如上图所示,队列是典型的 FIFO 数据结构。插入(insert)操作也称作入队(enqueue),新元素始终被添加在队列的末尾。 删除(delete)操作也被称为出队(dequeue)。 你只能移除 第一个元素

队列–实现

  1. 队列的初始化: 用一个动态数组与一个位置指针
  2. 队列的两个主要操作:入队与出队
	// store elements
    private List<Integer> data;         
    // a pointer to indicate the start position
    private int p_start;            
    public MyQueue() {
        data = new ArrayList<Integer>();
        p_start = 0;
    }
    /** Insert an element into the queue. Return true if the operation is successful. */
    public boolean enQueue(int x) {
        data.add(x);
        return true;
    };    
    /** Delete an element from the queue. Return true if the operation is successful. */
    public boolean deQueue() {
        if (isEmpty() == true) {
            return false;
        }
        p_start++;
        return true;
    }
    /** Get the front item from the queue. */
    public int Front() {
        return data.get(p_start);
    }
    /** Checks whether the queue is empty or not. */
    public boolean isEmpty() {
        return p_start >= data.size();
    }
缺点

动态数组的指针不断移动,空间越来越大,导致资源浪费。

循环队列

更有效的方法是使用循环队列。 具体来说,我们可以使用固定大小的数组两个指针来指示起始位置和结束位置。 目的是重用我们之前提到的被浪费的存储。
比如:先创建一个固定长度为5的数组,入队五个元素,此时队列满
队列满
再进行连续两次出队操作
在这里插入图片描述
此时,执行一次入队操作,从队列开头入队元素,合理运用空间。
在这里插入图片描述

循环队列的实现

在循环队列中,我们使用一个数组和两个指针(front 和 rear)。 front 表示队列的起始位置,rear 表示队列的结束位置。
除了最重要的入队(enQueue)和出队(deQueue),还添加了获取首尾元素值以及判断空/满的方法。
注意:在入队出队时,指针的操作rear=(rear+1)%MAXSIZE; / front=(front+1)%MAXSIZE;

```java
class MyCircularQueue {

    private int MAXSIZE;
    private int arr[];
    private int front;
    private int rear;
    private boolean flag;
    /** Initialize your data structure here. Set the size of the queue to be k. */
    public MyCircularQueue(int k) {

        MAXSIZE=k;
        arr= new int[MAXSIZE];
        front=0;
        rear=0;
        flag=false;
    }
    
    /** Insert an element into the circular queue. Return true if the operation is successful. */
    public boolean enQueue(int value) {
        
        if(isFull()==true)
            return false;
       
        arr[rear]=value;
        rear=(rear+1)%MAXSIZE;
        flag=true;

        return true;
    }
    
    /** Delete an element from the circular queue. Return true if the operation is successful. */
    public boolean deQueue() {
        
        if(isEmpty()==true)
            return false;
        front=(front+1)%MAXSIZE;
        flag=false;

        return true;
    }
    
    /** Get the front item from the queue. */
    public int Front() {
        if(isEmpty()==true)
            return -1;
        return arr[front];
    }
    
    /** Get the last item from the queue. */
    public int Rear() {

        if(isEmpty()==true)
            return -1;
        if(rear==0)
            return arr[MAXSIZE-1];
        else
            return arr[rear-1];
    }
    
    /** Checks whether the circular queue is empty or not. */
    public boolean isEmpty() {

        if(flag==false&&rear==front)
            return true;
        else
            return false;
    }
    
    /** Checks whether the circular queue is full or not. */
    public boolean isFull() {

        if(flag==true&&rear==front)
            return true;
        else
            return false;
    }
} 

后入先出的数据结构

与队列不同,栈是一个 LIFO 数据结构。插入操作在栈中被称作入栈 (push) 。与队列类似,总是在堆栈的末尾添加一个新元素。与队列不同的是,删除操作被称作退栈 (pop) ,将始终删除队列中相对于它的最后一个元素

在这里插入图片描述

栈的实现

  1. 队列的初始化:比队列更简便,只需要一个动态数组即可实现
  2. 队列的两个主要操作:入栈和退栈
// "static void main" must be defined in a public class.
class MyStack {
    private List<Integer> data;               // store elements
    public MyStack() {
        data = new ArrayList<>();
    }
    /** Insert an element into the stack. */
    public void push(int x) {
        data.add(x);
    }
    /** Checks whether the queue is empty or not. */
    public boolean isEmpty() {
        return data.isEmpty();
    }
    /** Get the top item from the queue. */
    public int top() {
        return data.get(data.size() - 1);
    }
    /** Delete an element from the queue. Return true if the operation is successful. */
    public boolean pop() {
        if (isEmpty()) {
            return false;
        }
        data.remove(data.size() - 1);
        return true;
    }
};

public class Main {
    public static void main(String[] args) {
        MyStack s = new MyStack();
        s.push(1);
        s.push(2);
        s.push(3);
        for (int i = 0; i < 4; ++i) {
            if (!s.isEmpty()) {
                System.out.println(s.top());
            }
            System.out.println(s.pop());
        }
    }
}

栈的使用——判断括号字符串是否有效

给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。

且有效字符串满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
class Solution {
    public boolean isValid(String s) {

        Stack<Character> stack=new Stack<>();
        
        for (char c: s.toCharArray())
        {
            if(stack.empty())
            {
                stack.push(c);
                continue;
            }
            if(c==')'&&stack.peek()=='('
               ||c==']'&&stack.peek()=='['
               ||c=='}'&&stack.peek()=='{')
                stack.pop();
            else
                stack.push(c);  
        }
        if (stack.isEmpty())
            return true;
        else
            return false;

    }
}

栈的使用——求逆波兰表达式(二元运算符)

根据逆波兰表示法,求表达式的值。

  1. 有效的运算符包括 +, -, *, / 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。
  2. 整数除法只保留整数部分。给定逆波兰表达式总是有效的。
    举例:输入: [“2”, “1”, “+”, “3”, “*”] 输出: 9 解释: ((2 + 1) * 3) = 9
class inversePolish {
    public int evalRPN(String[] tokens) {
        int a=0;int b=0;
        Stack <String> stack=new Stack<>();
        for (String e:tokens)
        {
            if(e.equals("+")||e.equals("-")||e.equals("*")||e.equals("/")) //字符串比较不能用==
            { //运算符则取出前两个变量
                b=Integer.parseInt(stack.peek());  //string→int
                stack.pop();
                a=Integer.parseInt(stack.peek());
                stack.pop();
            }
            switch(e)
            {
                case "+": stack.push(String.valueOf(a+b)); break;  //int→string
                case "-": stack.push(String.valueOf(a-b)); break;         
                case "*": stack.push(String.valueOf(a*b)); break;
                case "/": stack.push(String.valueOf(a/b)); break;
                default: stack.push(e);  //数字直接放入
            }        
        }
        return Integer.parseInt(stack.peek());
    }
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值