数据结构——队列

来源:互联网 发布:go 并发编程 编辑:程序博客网 时间:2024/04/28 16:42

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

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 0
原创粉丝点击