深入浅出数据结构——队列

队列

概念

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(FirstIn First Out) 入队列:进行插入操作的一端称为队尾(Tail/Rear) 出队列:进行删除操作的一端称为队头(Head/Front)

接口关系

在这里插入图片描述

方法描述

方法 抛出异常 返回特殊值
入队列 add(e) offer(e)
出队列 remeve() poll()
队首元素 element() peek()

方法实现

在这里插入图片描述

class Node {
    
    
    public int val;
    public Node next;

    public Node(int val) {
    
    
        this.val = val;
    }
}

public class MyQueue {
    
    
    public Node first;
    public Node last;

    //入栈
    public boolean offer(int val) {
    
    
        Node node = new Node(val);
        if(this.first == null) {
    
    
            this.first = node;
            this.last = node;
        }else {
    
    
            this.last.next = node;
            this.last = node;
        }
        return true;
    }

    //判断栈是否为空
    public boolean isEmpty() {
    
    
        if(this.first == null && this.last == null) {
    
    
            return true;
        }
        return false;
    }

    //出栈
    public int poll() throws RuntimeException{
    
    
        if(isEmpty()) {
    
    
            throw new RuntimeException("队列为空");
        }
        int ret = this.first.val;
        this.first = this.first.next;
        return ret;
    }

    //得到队头元素
    public int peek() {
    
    
        if(isEmpty()) {
    
    
            throw new RuntimeException("队列为空");
        }
        return this.first.val;
    }

}

用栈实现队列

力扣链接

class MyQueue {
    
    
    Stack<Integer> a;
    Stack<Integer> b;

    /** Initialize your data structure here. */
    public MyQueue() {
    
    
        a = new Stack<>();
        b = new Stack<>();
    }
    
    /** Push element x to the back of queue. */
    public void push(int x) {
    
    
        a.push(x);
    }
    
    /** Removes the element from in front of queue and returns that element. */
    public int pop() {
    
    
        if(b.empty()) {
    
    
            int size = a.size();
            for(int i = 0; i < size; i++) {
    
    
                b.push(a.pop());
            }
        }
        return b.pop();
    }
    
    /** Get the front element. */
    public int peek() {
    
    
        if(b.empty()) {
    
    
            int size = a.size();
            for(int i = 0; i < size; i++) {
    
    
                b.push(a.pop());
            }
        }
        return b.peek();
    }
    
    /** Returns whether the queue is empty. */
    public boolean empty() {
    
    
        return a.empty() && b.empty();
    }
}

循环队列

力扣链接

解决思路

抛出问题:队列是否可以用数组实现?

答案:可以的,如果把数组想成一个环,当数组满的时候将数据插入到数组头位置,这样就形成了循环队列。
在这里插入图片描述

问题1:front和rear相遇,到底是空还是满?

解决方法:
牺牲一个空间,来判断是否为满
判断当前rear的下一个是否为front


问题2:front和rear都会面临一个越界的问题?

解决方法:
加一个条件判断
当 (rear+1)%len == front 的时候,就要发生空间转换


代码实现

class MyCircularQueue {
    
    
    public int[] arr;
    public int rear;    //队尾
    public int front;   //队首
    public int len;

    public MyCircularQueue(int k) {
    
    
        arr = new int[k+1];
        len = k+1;
    }
    
    public boolean enQueue(int value) {
    
    
        if(isFull()) return false;
        arr[rear%len] = value;
        rear++;
        return true;
    }
    
    public boolean deQueue() {
    
    
        if(isEmpty()) return false;
        front++;
        return true;
    }
    
    public int Front() {
    
    
        if(isEmpty()) return -1;
        return arr[front%len];
    }
    
    public int Rear() {
    
    
        if(isEmpty()) return -1;
        return arr[(rear-1)%len]; 
    }
    
    public boolean isEmpty() {
    
    
        return rear == front;
    }
    
    public boolean isFull() {
    
    
        return (rear+1)%len == (front)%len;
    }
}

猜你喜欢

转载自blog.csdn.net/starry1441/article/details/114706413
今日推荐