【数据结构】用java实现队列

什么是队列?

队列(Queue)是一种基于元素的集合,特点是只允许在列表的一端(称为队尾rear)进行插入,而在列表的另一端(称为队头front)进行删除。因为队列遵循先进先出(FIFO,First In First Out)的原则,所以也被称为先进先出的线性表。
在这里插入图片描述

队列的基本操作

  • enqueue:将元素添加到队尾,也就是加入队列末尾。
  • dequeue:将元素从队头移除,只能从队头移除元素,实现先进先出(FIFO)。
  • peek:查看队列队头的元素,不对队列产生影响。
  • size:查看队列当前包含的元素数量。
  • isEmpty:判断队列是否为空
  • isFull:检查队列是否已满。
  • clear:清除队列中的所有元素。

数组模拟队列

在数组的队列中,我们通常使用两个指针来跟踪和更新队列的状态。一个是头部指针,指向队列中的第一个元素;另一个是尾部指针,指向队列中的最后一个有效元素的下一个位置。当我们添加一个新元素时,我们更新尾部指针。当我们移除一个元素时,我们更新头部指针。

/**
 * @Description: 基于数组的循环队列
 * 为了解决假溢出问题,把顺序表转为首尾相连的循环队列
 *     1.少用一个存储单元
 *         判空:front == rear
 *         判满:front == (rear+1)%maxSize
 *     2.设置一个标志变量,入列flag=1,出列flag=0
 *         判空:front==rear && flag==0
 *         判满:front==rear && flag==1
 *     3.设置一个计时器,入列num++,出列num--
 *         判空:num==0
 *         判满:num>0 && front==rear
 */
public class SqQueue<E> {
    private static final int DEFAULT_CAPACITY = 10;
    private E[] queue;
    private int front;
    private int rear;

    public SqQueue(E[] queue) {
        this.queue = queue;
        this.front = 0;
        this.rear = queue.length-1;
    }

    public SqQueue(int length) {
        this.queue = (E[]) new Object[length];
        this.front = 0;
        this.rear = 0;
    }

    public SqQueue() {
        this.queue = (E[]) new Object[DEFAULT_CAPACITY];
        this.front = 0;
        this.rear = 0;
    }

    public void offer(E e) {
        if(isFull()){
            System.out.println("队满");
            return;
        }
        queue[rear] = e;
        rear = (rear+1)%queue.length;
    }

    public E poll() {
        if(isEmpty()){
            System.out.println("队空");
            return null;
        }
        E e = queue[front];
        queue[front] = null;
        front = (front+1)%queue.length;
        return e;
    }

    public E getFront() {
        if(isEmpty()){
            System.out.println("队空");
            return null;
        }
        return queue[front];
    }

    public E getReal() {
        if(isEmpty()){
            System.out.println("队空");
            return null;
        }
        return queue[(rear-1+queue.length)%queue.length];
    }

    /*
     * 因为rear-front有可能为负数,如果为负数,则其绝对值表示的是空的存储空间的个数(出现假溢出了),
     * 加上queue.length,则就能求有多少元素.如果为正数,则其值直接就是队列中存储元素的个数
     */
    public int getSize() {
        return (rear-front+queue.length)%queue.length;
    }

    public boolean isEmpty() {
        return front==rear;
    }
    public boolean isFull(){
        return front==(rear+1)%queue.length;
    }

    public void display(){
        if(isEmpty()){
            System.out.println("队空");
            return;
        }
        System.out.print("队列的物理结构:{");
        for (E e : queue) {
            System.out.print(e+" ");
        }
        System.out.print("}\n队列的逻辑结构:{");
        for (int i = front; i!=rear ; i=(i+1)%queue.length) {
            System.out.print(queue[i]+" ");
        }
        System.out.println("}");
    }
}

链表模拟队列

链表由一系列节点组成,每个节点包含两个部分:元素和指向下一个节点的链接。在链表的队列中,我们同样保持一个头部和一个尾部链接。当我们添加一个新元素时,我们更新尾部链接。当我们移除一个元素时,我们更新头部链接。

public class Node<E> {
    public E data;
    public Node next;

    public Node(E data) {
        this.data = data;
        this.next = null;
    }

    public Node() {
        this.data = null;
        this.next = null;
    }
}

public class LinkListQueue<E> {
    Node front;
    Node rear;
    private int size;

    public LinkListQueue() {
    }
    public LinkListQueue(E[] arr) {
        for (E e : arr) {
            this.offer(e);
        }
    }

    public LinkListQueue(Node front) {
        this.front = front;
        this.rear = front;
        this.size = 0;
    }

    public void offer(E e) {
        Node p = new Node(e);
        if(isEmpty()){
            front = p;
            rear = p;
            size++;
            return;
        }
        rear.next = p;
        rear = p;
        size++;
    }

    public E poll() {
        if(isEmpty()){
            return null;
        }
        E e = (E) front.data;
        front = front.next;
        size--;
        return e;
    }

    public E getFront() {
        if (isEmpty()){
            return null;
        }
        return (E) front.data;
    }

    public E getReal() {
        if (isEmpty()){
            return null;
        }
        return (E) rear.data;
    }

    public int getSize() {
        return size;
    }

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

    public void display() {
        Node e = front;
        System.out.print("队列的结构为:{");
        if(e.next==null){
            System.out.println(e.data+"}");
            return;
        }
        while (e.next!=null){
            System.out.print(e.data+"-->");
            e = e.next;
        }
        System.out.println(e.data+"}");
    }
}

队列测试代码

public class test {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String[] q = {"新","年","快","乐","这","是","一","个","队","列"};
//        SqQueue<String> queue = new SqQueue<String>(q);
//        LinkListQueue<String> queue = new LinkListQueue<String>(new Node<String>());
        LinkListQueue<String> queue = new LinkListQueue<String>(q);
        queue.display();
        boolean flag = true;
        String c = null;
        String e = null;
        while (flag){
            System.out.print("请输入要进行的操作:");
            c = sc.next();
            switch (c){
                case "offer":
                    System.out.println("请输入要插入的元素");
                    e = sc.next();
                    queue.offer(e);
                    break;
                case "poll":
                    e = queue.poll();
                    if(e!=null){
                        System.out.println("出队元素为:"+e);
                    }
                    break;
                case "getFront":
                    e = queue.getFront();
                    if(e!=null) {
                        System.out.println("栈头元素为:" + e);
                    }
                    break;
                case "getRear":
                    e = queue.getReal();
                    if(e!=null) {
                        System.out.println("栈尾元素为:" + e);
                    }
                    break;
                case "display":
                    queue.display();
                    break;
                default:
                    flag = false;
                    break;
            }
        }
    }
}

Java封装好的队列

Java提供了java.util.Queue接口,该接口在Java集合框架中表示一个队列。Queue接口定义了在队列两端插入和删除元素的方法。它的实现类如LinkedList。LinkedList是一个以双向链表实现的List,在实现时提供了队列的特性。

public class QueueTest {
    public static void main(String[] args) {
        // 创建队列实例
        Queue<Integer> queue = new LinkedList<>();

        // 判断队列是否为空
        System.out.println("队列是否为空:" + queue.isEmpty());

        // 入队操作
        queue.add(1);
        queue.add(2);
        queue.add(3);
        queue.add(4);

        // 获取队头元素
        System.out.println("队头元素:" + queue.peek());

        // 出队操作
        System.out.println("出队元素:" + queue.remove());

        // 判断队列是否为空
        System.out.println("队列是否为空:" + queue.isEmpty());
    }
}

队列实际应用

  • 计算机系统中的任务调度:计算机系统常常需要管理大量的执行任务,队列是实现任务管理的一种重要方式。例如,CPU的任务调度,打印机的打印任务等。
  • 网络中的数据传输:在网络中,数据包的发送和接收都需要队列进行处理。发送数据包时,数据包会被放入队列,等待网络可用时发送;接收数据包时,数据包会被放入队列,等待应用程序处理。
  • 在线程之间进行同步:在多线程编程中,队列常常用于实现线程之间的同步,也就是一个线程生成的数据,另一个线程消费的数据。

队列的这些应用都充分体现了其“先进先出”的特性,能够保证元素处理的顺序性和公平性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值