数据结构——队列

一、队列的顺序存储结构实现

public class Queue<E> {
    private Object[] data;
    // 默认容量
    private int maxCapacity = 10;
    // 队头
    private int font;
    // 队尾
    private int rear;

    public Queue(int capacity) {
        if (capacity >= 0) {
            maxCapacity = capacity;
            data = new Object[maxCapacity];
            font = 0;
            rear = 0;
        } else {
            throw new IllegalArgumentException("初始化大小不能小于0:" + capacity);
        }

    }

    // 入队
    public boolean add(E e) {
        if (rear == maxCapacity) {
            throw new RuntimeException("队列已满,无法插入新的元素!");
        } else {
            data[rear] = e;
            rear++;
            return true;
        }

    }

    // 出队
    public E poll() {
        if (font == rear) {
            throw new RuntimeException("空队列异常!");
        } else {
            E value = (E) data[font];
            data[font] = null;
            font++;
            return value;
        }

    }

    // 返回队头元素
    public E peek() {
        if (font == rear) {
            throw new RuntimeException("空队列异常!");
        } else {
            return (E) data[font];
        }
    }

    // 队列长度
    public int length() {
        return rear - font;
    }

    // 队满
    public boolean full() {
        return rear == maxCapacity;
    }

    // 队空
    public boolean empty() {
        return font == rear;
    }

    // 清空队列
    public void clear() {
        Arrays.fill(data, font, rear, null);
        font = 0;
        rear = 0;
    }

二、循环队列

public class LoopQueue<E> {
    private Object[] data;
    private int maxCapacity = 10;
    // 队头
    private int font;
    // 队尾
    private int rear;
    // 计数
    private int count;

    public LoopQueue(int size) {
        if (size >= 0) {
            maxCapacity = size;
            data = new Object[maxCapacity];
            font = 0;
            rear = 0;
            count = 0;
        } else {
            throw new RuntimeException("初始化大小不能小于0:" + size);
        }

    }

    public boolean add(E e) {
        if (count == maxCapacity) {
            throw new RuntimeException("队列已满,无法插入新的元素!");
        } else {
            data[rear] = e;
            rear = (rear + 1) % maxCapacity;
            count++;
            return true;
        }
    }

    // 出队
    public E poll() {
        if (font == rear) {
            throw new RuntimeException("空队列异常!");
        } else {
            E value = (E) data[font];
            data[font] = null;
            font = (font + 1) % maxCapacity;
            count++;
            return value;
        }

    }

    // 返回队头元素
    public E peek() {
        if (font == rear) {
            throw new RuntimeException("空队列异常!");
        } else {
            return (E) data[font];
        }
    }

    // 队列长度
    public int size() {
        return count;
    }

    // 队满
    public boolean full() {
        return count == maxCapacity;
    }

    // 队空
    public boolean empty() {
        return count == 0;
    }

    // 清空队列
    public void clear() {
        Arrays.fill(data, font, rear, null);
        font = 0;
        rear = 0;
        count = 0;
    }
}

三、以链表结构的形式实现

public class LinkedQueue<E> {
    private static class Node<E> {
        private Node<E> next;
        private E value;

        public Node(E value, Node<E> next) {
            this.next = next;
            this.value = value;
        }
    }

    private Node<E> font;
    private Node<E> rear;
    private int count;

    public LinkedQueue() {
        font = null;
        rear = null;
    }

    // 入队
    public boolean add(E e) {
        if (count == 0) {
            font = new Node<E>(e, null);
            rear = font;
        } else {
            Node<E> newNode = new Node<E>(e, null);
            rear.next = newNode;
            rear = newNode;
        }

        count++;
        return true;
    }

    // 出队
    public E poll() {
        if (count == 0) {
            throw new RuntimeException("空队列异常!");
        }
        E value = font.value;
        font = null;
        count--;
        return value;
    }

    // 返回队头元素
    public E peek() {
        if (count == 0) {
            throw new RuntimeException("空队列异常!");
        } else {
            return font.value;
        }
    }

    public int size() {
        return count;
    }

    // 队空
    public boolean empty() {
        return count == 0;
    }

四、总结

      队列顺序存储结构的不足:假设这个队列的总个数不超过5个,但目前如果接着入队的话,因数组末尾元素已经占用,再向后加,就会产生数组越界的错误,可实际上,我们的队列在下标为0和1的地方还是空闲的。我们把这种现象叫做“假溢出”。

对于循环队列与链队列的比较,可以从两方面来考虑:
      从时间上,其实它们的基本操作都是常数时间,即都为0(1)的,不过循环队列是事先申请好空间,使用期间不释放,而对于链队列,每次申请和释放结点也会存在一些时间开销,如果入队出队频繁,则两者还是有细微差异。
      对于空间上来说,循环队列必须有一个固定的长度,所以就有了存储元素个数和空间浪费的问题。而链队列不存在这个问题,尽管它需要一个指针域,会产生一些空间上的开销,但也可以接受。所以在空间上,链队列更加灵活。

     总的来说,在可以确定队列长度最大值的情况下,建议用循环队列,如果你无法预估队列的长度时,则用链队列。
      用数组实现队列时,如果不移动,随着数据的不断读写,会出现假满队列的情况。即尾数组已满但头数组还是空的。循环队列也是一种数组,只是它在逻辑上把数组的头和尾相连,形成循环队列,当数组尾满的时候,要判断数组头是否为空,不为空继续存放数据,可以有效的利用资源。但是用循环队列有个小麻烦,不好判断数列是为空还是为满;
      链队列就不存在上面的问题。“循环队列”最大优点就是节省空间和少分配空间,而链队列多了一点点地址存储开销。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值