【java数据结构】队列

此篇博客希望对你有所帮助(帮助你了解队列),不懂的或有错误的也可在评论区留言,错误必改评论必回!!!持续关注,下一篇博客是树!!!整篇博客的代码都在Gitee中(代码链接放下文章结尾)。

一、队列的概念

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

在这里插入图片描述
队列:如等地铁一样,先来的先排队坐地铁,后来的后排队坐地铁。

二、队列的使用

在java中,Queue是个接口,底层是通过链表实现的。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  • 当使用有容量限制的队列时,offer(E e)通常比add(E e)方法更好用,因为offer在无法插入元素时不会抛出异常,而是返回false。
  • poll()与remove()方法相比,poll()方法在队列为空时不会抛出异常。
  • peek()与element()方法相比,peek()方法在队列为空时不会抛出异常。

三、队列的模拟实现(双链表)

这里用单链表或双链表都可以实现队列。但是我们这里实现队列是通过双链表模拟的。
单链表实现思路:
我们需要定义一个标记尾节点的引用,下来就是尾插入,头删除,有兴趣的可以自行实现以下哦!

    public void offer(int val) {
    }

    public int poll() {
    }

    public int peek() {
    }

    public int size() {
    }

    public boolean isEmpty() {
    }

创建节点

 public static class ListNode {
        ListNode next;
        ListNode prev;
        int value;

        ListNode(int value) {
            this.value = value;
        }
    }

    ListNode first; // 队头
    ListNode last; // 队尾
    int size = 0;

isEmpty()

public boolean isEmpty() {
        return first==null;
    }

size()

 public int size() {
        return size;
    }

offer(int val)

    public void offer(int val) {
        ListNode cur=new ListNode(val);
        if(first==null){
            first=last=cur;
        }
        last.next=cur;
        cur.prev=last;
        cur.next=null;
        last=cur;
    }

poll()

public class EmptyException extends RuntimeException{
    public EmptyException() {
    }

    public EmptyException(String message) {
        super(message);
    }
}

    public int poll() {
        ListNode cur=first;
        if(first==null){
            throw new EmptyException();
        }else if(first==last){
            size--;
            return first.value;
        }else {
            first=first.next;
            first.prev=null;
            size--;
            return cur.value;
        }
    }

peek()

    public int peek() {
        if(first==null){
            throw new EmptyException();
        }else{
            return first.value;
        }
    }

四、循环队列

实际中我们有时还会使用一种队列叫循环队列。环形队列通常使用数组实现。

在这里插入图片描述

4.1 循环队列下标偏移

在这里插入图片描述
在这里插入图片描述

4.2 如何区分队列是空还是满

  1. 通过添加 size 属性记录,如果size等于数组长度则满,否则不满
  2. 保留一个位置,
  3. 使用标记,判断尾的下一个是不是头

4.4 设计循环队列

设计循环队列
在这里插入图片描述

public class MyCircularQueue {
    public int front;
    public int rear;
    public int[] elem;
    public int useSize;

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

    public boolean enQueue(int value) {
        if (isFull()) {
            return false;
        }
        elem[rear] = value;
        rear = (rear + 1) % elem.length;
        useSize++;
        return true;
    }

    public boolean deQueue() {
        if (isEmpty()) {
            return false;
        }
        front = (front + 1) % elem.length;
        useSize--;
        return true;
    }

    public int Front() {
        if (isEmpty()) {
            return -1;
        }
        return elem[front];
    }

    public int Rear() {
        if (isEmpty()) {
            return -1;
        }
        int index = (front+useSize-1)% elem.length;
        return elem[index];
    }

    public boolean isEmpty() {
        return useSize == 0;
    }

    public boolean isFull() {
       return useSize==elem.length;
    }
}

五、双端队列(Deque)

双端队列(deque)是指允许两端都可以进行入队和出队操作的队列,deque 是 “double ended queue” 的简称。 那就说明元素可以从队头出队和入队,也可以从队尾出队和入队
Deque是一个接口,使用时必须创建LinkedList的对象。

在这里插入图片描述

Deque<Integer> stack = new ArrayDeque<>();//双端队列的线性实现
Deque<Integer> queue = new LinkedList<>();//双端队列的链式实现

六、练习

用队列实现栈
在这里插入图片描述

public class MyStackUseQueue {
    public Queue<Integer> queue1;
    public Queue<Integer> queue2;
    public  MyStackUseQueue() {
        queue1=new LinkedList<>();
        queue2=new LinkedList<>();
    }
    public void push(int x) {
        if(!queue1.isEmpty()){
            queue1.offer(x);
        } else if (!queue2.isEmpty()) {
            queue2.offer(x);
        }else{
            queue1.offer(x);
        }
    }

    public int pop() {
        if(empty()){
            return -1;
        }
        if(!queue1.isEmpty()){
            int size=queue1.size();
            for(int i=0;i<size-1;i++){
                queue2.offer(queue1.poll());
            }
            return queue1.poll();
        }else{
            int size=queue2.size();
            for(int i=0;i<size-1;i++){
                queue1.offer(queue2.poll());
            }
            return queue2.poll();
        }
    }

    public int top() {
        if(empty()){
            return -1;
        }
        if(!queue1.isEmpty()){
            int size=queue1.size();
            int val=0;
            for(int i=0;i<size;i++){
                val=queue1.peek();
                queue2.offer(queue1.poll());
            }
            return val;
        }else{
            int size=queue2.size();
            int val=0;
            for(int i=0;i<size;i++){
                val=queue2.peek();
                queue1.offer(queue2.poll());
            }
            return val;
        }
    }

    public boolean empty() {
        return queue1.isEmpty()&&queue2.isEmpty();
    }
}

用栈实现队列
在这里插入图片描述

public class MyQueueUseStack {
    public ArrayDeque<Integer> stack1;
    public ArrayDeque<Integer> stack2;


    public MyQueueUseStack() {
        stack1 = new  ArrayDeque<>();
        stack2 = new  ArrayDeque<>();
    }

    public void push(int x) {
        stack1.push(x);
    }

    public int pop() {
        if(empty()) {
            return -1;
        }
        if(stack2.isEmpty()) {
            //第一个栈里面所有的元素 放到第二个栈当中
            while(!stack1.isEmpty()) {
                stack2.push(stack1.pop());
            }
        }
        return stack2.pop();
    }

    public int peek() {
        if(empty()) {
            return -1;
        }
        if(stack2.isEmpty()) {
            //第一个栈里面所有的元素 放到第二个栈当中
            while(!stack1.isEmpty()) {
                stack2.push(stack1.pop());
            }
        }
        return stack2.peek();
    }

    public boolean empty() {
        return stack1.isEmpty() && stack2.isEmpty();
    }
}

此篇博客的代码!

### Java队列数据结构的实现与使用 #### 队列简介 队列是一种遵循先进先出(FIFO, First In First Out)原则的数据结构。这意味着最早进入队列的元素会最先被移除。为了更好地管理和操作这些元素,Java 提供了 `Queue` 接口以及多个具体的实现类[^3]。 #### Queue接口的主要方法 - **add(E e)** 和 **offer(E e)**:用于向队列中插入一个新元素。两者的区别在于当队列已满时,前者抛出异常而后者返回false。 - **remove()** 和 **poll()**:用来删除并获取队首元素。如果队列为空,则前者抛出NoSuchElementException异常,后者则返回null。 - **element()** 和 **peek()**:仅查看而不移除队首元素;若队列为空,前者抛出NoSuchElementException异常,后者返回null。 #### 常见的具体实现类 1. **LinkedList** 作为双向链表的一种形式,它不仅实现了List接口还实现了Deque双端队列接口,因此可以当作普通的线性表或者栈、队列来使用。对于基本的入队和出队操作效率较高。 2. **ArrayBlockingQueue** 基于数组实现的一个有界阻塞队列,在多线程环境中非常有用。创建对象的时候需要指定其大小,并且可以选择是否公平竞争锁机制。 3. **PriorityQueue** 此类型的队列按照优先级顺序排列,默认情况下自然排序升序或通过比较器定制化规则。每次取出都是当前最高/最低优先级别的那个节点。 #### 使用示例 下面给出一段简单的代码片段演示如何利用`LinkedList`实例化一个队列来进行基础的操作: ```java import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args){ // 创建一个新的队列 Queue<String> queue = new LinkedList<>(); // 添加元素到队尾 queue.offer("First"); queue.offer("Second"); queue.offer("Third"); System.out.println(queue); // 输出: [First, Second, Third] // 移除并打印队头元素 String headElement = queue.poll(); System.out.println(headElement); // 输出: First // 查看但不移除新的队头元素 System.out.println(queue.peek()); // 输出: Second } } ``` 上述程序展示了怎样创建一个字符串类型的队列,依次加入三个不同的值之后再逐步处理它们直到只剩下一个为止[^2]。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值