java数据结构YZP专栏-----队列

本文详细介绍了如何使用数组和链表实现队列数据结构,包括入队、出队操作,并提供了Java代码示例。通过动画演示加深了理解,同时展示了两种实现方式的不同之处。
主文章(数据结构的索引目录—进不去就说明我还没写完)
https://blog.youkuaiyun.com/grd_java/article/details/122377505
模拟数据结构的网站:https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
源码(码云):https://gitee.com/yin_zhipeng/data_structures_and_algorithms_in_java.git
队列
  1. 一种先入先出的数据结构
  2. 每次访问数据,都只能从队列的头部访问,插入数据只能从队列尾部访问(普通队列)

1.数组实现(Array Implementation)

动画演示
  1. 入队列
    请添加图片描述
  2. 出队列
    请添加图片描述
  3. 循环队列
    请添加图片描述
思路
  1. 创建数组作为队列,定义capacity表示队列(数组)大小,有效的存储空间只有capacity-1个,需要保留一个空间做判断(具体看上图循环队列)
  2. 定义front和tail表示队列的头指针和尾指针
  3. 假设队列9个空间,既然要实现循环,那么第10个元素,应该插入到第一个位置(第一个位置为空的话)
  4. 通过10%capacity=1,可以算出第10个元素应该插入到第一位,但是如果1位置有元素,表示不能插入,队列满
  5. 如果front==rear表示队列为空,
  6. 如果(tail+1)%capacity== front 表示队列满,不能继续插入数据
  7. 后移一位下标(front/tail+ 1)%capacity
  8. 有效元素个数tail + capacity - head; 加capacity是因为tail-head可能是负数比如-1,而%capacity的值是循环队列的下标,,-3%2=-1,不是+1,会下标越界
  9. 当我们想取到队列第三个值的时候,(head+3)%capacity即可
代码:com/yzpnb/data_structures/queues/array_implementation/ArrayQueue.java
  1. 运行效果
    在这里插入图片描述
public class ArrayQueue<T> {
    private T[] queue;//数组作为队列
    private int capacity;//队列容量
    private int head;//头指针
    private int tail;//尾部指针,指向末尾元素的下一个位置,如果tail的下一个位置就是head,则不允许插入数据

    //构造
    public ArrayQueue(int capacity){
        queue = newArray(capacity);//队列
        this.capacity = capacity;//容量
        head = 0;//头指针
        tail = 0;//尾指针
    }

    /**
     * 构建数组,直接转型为T(泛型)
     * @param size 大小
     */
    private T[] newArray(int size){
        return (T[])new Object[size];
    }
    //入队列
    public boolean enQueue(T o){
        queue[tail] = o;
        int newTail = (tail+1) % capacity;//指针后移一位
        if(newTail == head)
            throw new IndexOutOfBoundsException("Queue full!!!队列满");
        tail = newTail;
        return true;
    }
    //出队列
    public T deQueue(){
        if(head == tail)
            throw new IndexOutOfBoundsException("Queue empty!!!队列为空");
        T deQueue = queue[head];//获取队列头数据
        queue[head] = null;//置为null
        head = (head + 1) % capacity;//下标后移
        return deQueue;
    }

    //获取指定下标结点,以用户角度看,下标不是循环的
    public T get(int i){
        int size = size();//获取有效个数
        if(i<0 || i > size) {
            final String msg = "Index " + i + ", queue size " + size;
            throw new IndexOutOfBoundsException(msg+"下标超出队列当前元素数量");
        }
        int index = (head + i) % capacity;//找到用户想要元素的下标
        return queue[index];
    }
    //有效元素个数tail + capacity - head; 加capacity是因为tail-head可能是负数比如-1
    public int size(){
        // Can't use % here because it's not mod: -3 % 2 is -1, not +1.
        int diff = tail - head;
        if (diff < 0)//如果是负数
            diff += capacity;//+capacity
        return diff;
    }


    public void printer(){
        System.out.print("队列:");
        int size = size();
        for(int i = 0;i<size;i++){
            System.out.print(queue[((head+i)%capacity)]+" ");
        }
        System.out.println();
    }
    public static void main(String[] args) {
        ArrayQueue<Integer> queue = new ArrayQueue<Integer>(4);
        queue.enQueue(1);queue.enQueue(2);queue.enQueue(3);
        queue.printer();
        System.out.println("出队列"+queue.deQueue());
        System.out.println("出队列"+queue.deQueue());
        queue.printer();
        queue.enQueue(4);
        queue.printer();
        System.out.println("第二个元素:"+queue.get(1));
    }
}

2.链表实现(Linked List Implementation

动画演示
  1. 入队列
    请添加图片描述
  2. 出队列
    请添加图片描述
实现思路
  1. 定义head和tail分别指向队头和队尾结点,构造队列时,直接创建一个空结点作为头
  2. 插入结点时,tail指向的结点的后缀,指向新插入结点,tail指向新插入结点
  3. 出队列,返回当前头结点(队列第二个结点,第一个是辅助),head指向当前头结点的后继
代码:com/yzpnb/data_structures/queues/linked_list_implementation/LinkedQueue.java
  1. 运行效果
    在这里插入图片描述
import java.util.Collection;

public class LinkedQueue<E> {
    /**
     * Linked list node class 单链表结点
     */
    static class Node<E> {
        E item;

        Node<E> next;//后继

        Node(E x) { item = x; }
    }
    private final int capacity;//最大容量
    transient Node<E> head;//头
    private transient Node<E> last;//尾

    /**
     * 构造队列
     */
    public LinkedQueue(int capacity) {
        if (capacity <= 0) throw new IllegalArgumentException();
        this.capacity = capacity;
        last = head = new Node<E>(null);
    }
    //根据集合构造
    public LinkedQueue(Collection<? extends E> c) {
        this(Integer.MAX_VALUE);
        int n = 0;
        for (E e : c) {
            if (e == null)
                throw new NullPointerException();
            if (n == capacity)
                throw new IllegalStateException("Queue full");
            enqueue(e);
            ++n;
        }
    }

    //入队列
    public void enqueue(E e) {
        Node<E> node = new Node<E>(e);
        last = last.next = node;
    }

    public E dequeue(){
        E peek = peek();
        head = head.next;
        return peek;
    }

    //获取头结点(队列第二个结点)
    public E peek() {
        Node<E> first = head.next;
        if (first == null)
            return null;
        else
            return first.item;
    }

    public void printer(){
        System.out.print("队列:");
        Node<E> first = head.next;
        while(first != null){
            System.out.print(first.item+" ");
            first = first.next;
        }
        System.out.println();
    }
    public static void main(String[] args) {
        LinkedQueue<Integer> queue = new LinkedQueue<Integer>(4);
        queue.enqueue(1);queue.enqueue(2);queue.enqueue(3);
        queue.printer();
        System.out.println("出队列"+queue.dequeue());
        System.out.println("出队列"+queue.dequeue());
        queue.printer();
        System.out.println("入队列4");
        queue.enqueue(4);
        queue.printer();
    }

}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ydenergy_殷志鹏

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

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

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

打赏作者

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

抵扣说明:

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

余额充值