队列总结(Java实现)

我们可以将队列看成小朋友排队打饭:

  • 有小朋友到指定的地点了-->出队
  • 有新的小朋友加入了-->入队
  • 相对于栈而言,队列的特性是:先进先出
  • 先排队的小朋友肯定能先打到饭!

栈和队列的比较:

栈(Stack)和队列(Queue)是两种操作受限的线性表。这种受限表现在:栈的插入和删除操作只允许在表的尾端进行(在栈中成为“栈顶”),满足“First In Last Out”;队列只允许在表尾插入数据元素,在表头删除数据元素,满足“First In First Out”。它们都可以通过顺序结构和链式结构实现,插入与删除的时间复杂度都是O1),在空间复杂度上两者也一样。 

队列的应用场景:

  • 计算机系统中各种资源的管理
  • 消息缓冲器的管理
  • 广度优先搜索遍历

顺序队列的实现:

顺序队列的实现也可以使用数组来完成,同栈的实现一样,只是栈是在同一端进行压栈和进栈操作,而队列是在一端做push,另一端做pop操作。

我们在实现顺序栈时使用头指针“front”和尾指针“rear”分别进行出队和入队操作,但普通的队列如上图所示,会发生“假溢出”现象,所以我们通常将数组弄成一个环状,即队头和队尾相连,这样就形成了“循环队列”,同时也解决了“假溢出”现象。循环队列是改进版的顺序队列。

对于普通队列的push或pop我们只需要对尾指针或头指针进行自增操作即可,但是循环队列我们就不能单纯的进行自增,当front或rear=maxSize-1时我们就不能进行自增操作了,比如一个队列尾长度为4的数组datas[4],那么当front或rear需要在0,1,2,3之间进行循环“推进”,以此达到循环队列的效果。所以我们可以使用rear = (rear+1)%maxSize ;front = (front+1)%maxSize ;公式进行指针计算。

需要注意的是,队空状态的条件为:front = rear。而如果整个队列全部存满数据那么,队满的条件也是front = rear,所以循环队列需要损失一个存储空间,如下图:

顺序队列的基本操作实现:

  • 判断队列是否为空
  • 判断队列是否满了
  • 入队
  • 出队
  • 遍历
package com.hjy.datastructure.queue;

/**
 * 顺序队列的基本操作(数组实现)
 *
 * @param <T>
 */
public class ArrayQueue<T> {
    private T[] elementData; // 使用数组作为队列的容器
    private int maxSize; // 队列的容量
    private int front; // 头指针
    private int rear; // 尾指针

    /**
     * 初始化队列
     *
     * @param maxSize
     */
    public ArrayQueue(int maxSize) {
        if (maxSize < 1) {
            maxSize = 1;
        }
        this.maxSize = maxSize;
        this.front = 0;
        this.rear = 0;
        this.elementData = (T[]) new Object[this.maxSize];
    }

    /**
     * 判断队列是否为空
     *
     * @return
     */
    public boolean isEmpty() {
        if (front == rear) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 判断队列是否满了
     *
     * @return
     */
    public boolean isFull() {
        if ((rear + 1) % this.maxSize == front) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 入队
     *
     * @param e
     * @return
     */
    public T enQueue(T e) {
        if (isFull()) {
            System.out.println("队列已经满了");
            return null;
        } else {
            elementData[rear] = e; // 进队
            rear = (rear + 1) % maxSize; // 队尾指针+1.
            return e;
        }
    }

    /**
     * 出队
     *
     * @return
     */
    public T deQueue() {
        if (isEmpty()) {
            System.out.println("队列是空的");
            return null;
        } else {
            T e = elementData[front]; // 出队
            front = (front + 1) % maxSize; // 队头指针+1
            return e;
        }
    }

    /**
     * 遍历队列
     */
    public void traverse() {
        int i = front;
        System.out.println("遍历队列:");
        while (i != rear) {
            System.out.print(elementData[i] + " ");
            i = (i + 1) % maxSize;
        }
        System.out.println();
    }

    public static void main(String[] args) {
        ArrayQueue q = new ArrayQueue(5);
        // 判断是否为空
        System.out.println("是否为空:" + q.isEmpty());

        // 入队
        System.out.println("入队:" + q.enQueue(1));
        System.out.println("入队:" + q.enQueue(2));
        System.out.println("入队:" + q.enQueue(3));
        System.out.println("入队:" + q.enQueue(4));

        // 判断队列是否满了
        System.out.println("是否满了:" + q.isFull());
        // 遍历队列
        q.traverse();

        // 出队
        System.out.println("出队:" + q.deQueue());
        System.out.println("出队:" + q.deQueue());
        // 遍历
        q.traverse();

        // 继续入队
        System.out.println("入队:" + q.enQueue(5));
        System.out.println("入队:" + q.enQueue(6));
        System.out.println("入队:" + q.enQueue(7));

        // 遍历
        q.traverse();
    }
}

输出结果: 

是否为空:true
入队:1
入队:2
入队:3
入队:4
是否满了:true
遍历队列:
1 2 3 4 
出队:1
出队:2
遍历队列:
3 4 
入队:5
入队:6
队列已经满了
入队:null
遍历队列:
3 4 5 6 

 链式队列的基本操作实现:

  • 判断队列是否为空
  • 入队
  • 出队
  • 返回元素个数
  • 遍历队列
package com.hjy.datastructure.list;

/**
 * 定义一个单链表
 */
public class Node<T> {
    // 存储的数据
    public T value;
    // 下一个节点的引用
    public Node<T> next;

    public Node(T value) {
        this.value = value;
    }
}

 

package com.hjy.datastructure.queue;

import com.hjy.datastructure.list.Node;

public class LinkedQueue<T> {
    private Node<T> front; // 队头
    private Node<T> rear; // 队尾
    private int size; // 实际元素个数


    /**
     * 是否为空
     * @return
     */
    public boolean isEmpty() {
        return (front == null && rear == null) ? true : false;
    }

    /**
     * 入队
     * @param value
     */
    public T enQueue(T value) {
        Node<T> node = new Node<>(value);
        if (isEmpty()) {
            front = rear = node;
        } else {
            rear.next = node;
            rear = node;
        }
        size++;
        return value;
    }

    /**
     * 出队
     * @return
     */
    public T deQueue() {
        if (isEmpty()) {
            System.out.println("队列为空");
            return null;
        }

        Node<T> node = front;
        front = node.next;
        size--;

        if (size == 0) {
            // 删除掉最后一个元素
            rear = front = null;
        }
        return node.value;
    }

    /**
     * 元素数量
     * @return
     */
    public int size() {
        return this.size;
    }

    /**
     * 遍历队列
     */
    public void traverse() {
        Node<T> node = front;
        System.out.println("遍历队列:");
        while (node != null) {
            System.out.print(node.value + " ");
            node = node.next;
        }
        System.out.println();
    }

    public static void main(String[] args) {
        LinkedQueue q = new LinkedQueue();
        // 判断是否为空
        System.out.println("是否为空:" + q.isEmpty());

        // 入队
        System.out.println("入队:" + q.enQueue(1));
        System.out.println("入队:" + q.enQueue(2));
        System.out.println("入队:" + q.enQueue(3));
        System.out.println("入队:" + q.enQueue(4));

        // 遍历队列
        q.traverse();

        // 出队
        System.out.println("出队:" + q.deQueue());
        System.out.println("出队:" + q.deQueue());
        // 遍历
        q.traverse();

        // 继续入队
        System.out.println("入队:" + q.enQueue(5));
        System.out.println("入队:" + q.enQueue(6));
        System.out.println("入队:" + q.enQueue(7));

        // 遍历
        q.traverse();

        System.out.println("元素数量:" + q.size());
    }
}


输入结果:

是否为空:true
入队:1
入队:2
入队:3
入队:4
遍历队列:
1 2 3 4 
出队:1
出队:2
遍历队列:
3 4 
入队:5
入队:6
入队:7
遍历队列:
3 4 5 6 7 
元素数量:5

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@从入门到入土

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值