Java面向对象编程 - 实现一个定容量的队列

目 录

  • 1 队列

  • 2 实现定容量队列(底层是数组)

  • 3 实现定容量队列(底层是双向链表)


1 队列

队列是一种线性的数据结构。

它有两个主要的功能方法:一个是存入(put),一个是取出(take)。

存入就是把元素存入队列中。

取出就是从队列中拿走这个元素,拿走后队列中就不存在这个元素了。

队列的存入和取出受FIFO(先进先出)原则限制,即最先存入队列的元素一定最先被取出。

与此相对应的一种数据结构是栈,最先存入栈的元素一定最后被取出。

实现一个队列,底层可以用数组,也可以用链表。

下文将分别用数组和双向链表实现一个定容量的队列。设计如下方法:

(1)存入put(),取出take();

(2)返回队列中元素个数size();

(3)返回队列当前容量大小length();

(4)清空队列clear()。


2 实现定容量队列(底层是数组)

  • 定义队列类MyQueue

  1. 定义属性:数组array、队列中元素个数int size、队列容量int capacity

    private E[] array;
    private int capacity;
    private int size;
  1. 定义方法:

(1)构造方法

    public MyQueue(int capacity) {
        this.capacity = capacity;
        this.array = (E[]) new Object[capacity];
        this.size = 0;
    }

(2)put方法

    /**
     *
     * @param e 存入的元素
     */
    public void put(E e){
//        判断队列是否已满,如果已满,不能添加元素
        if(size == capacity){
            throw new ArrayIndexOutOfBoundsException();
        }
//        用下标体现存入元素的先后顺序,下表越大表示越晚存入
        array[size] = e;
        size++;
    }

(3)take方法

    /**
     *
     * @return 取出的元素
     */
    public E take(){
//        判断队列是否为空,如果为空,不能取出元素
        if (array != null){
//            先进先出,第0个位置存着最早存入的元素,应将其取出
            E e = array[0];
//            剩余位置元素依次向前挪,下次还是从第0个位置取出
            for (int i = 1; i < size; i++) {
                array[i - 1] = array[i];
            }
            array[size] = null;
            size--;
            return e;
        }
        throw new ArrayIndexOutOfBoundsException();
    }

(4)clear方法

这里不考虑在物理上删除原来的数组,而是暂时先用new关键字新建一个数组。

    public void clear(){
        this.array = (E[]) new Object[capacity];
        this.size = 0;
    }

(5)其他方法

    public int size(){
        return this.size;
    }

    public int length(){
        return this.capacity;
    }

    public void setCapacity(int capacity){
        this.capacity = capacity;
    }

    public double capacityRate(){
        double capacity = this.capacity;
        double size = this.size;
        return size/capacity;
    }

    public String getArray(){
        return Arrays.toString(this.array);
    }

  • 测试

写下面这段程序简单测试一下。

public class Main {
    public static void main(String[] args) {
        MyQueue<String> myQueue = new MyQueue<>(100);
        for (int i = 0; i < 50; i++) {
            myQueue.put("x");
            System.out.println(myQueue.getArray());
            System.out.println(myQueue.size());
            System.out.println(myQueue.capacityRate());
        }
        for (int i = 0; i < 20; i++) {
            myQueue.take();
            System.out.println(myQueue.getArray());
            System.out.println(myQueue.size());
            System.out.println(myQueue.capacityRate());
        }
        myQueue.clear();
        System.out.println(myQueue.getArray());
        System.out.println(myQueue.size());
        System.out.println(myQueue.capacityRate());
    }
}


3 实现定容量队列(底层是双向链表)

  • 定义结点类Node

  1. 定义属性:结点值value、下一结点next、上一结点front

    private E value;
    private Node<E> next;
    private Node<E> front;
  1. 定义一系列getter、setter方法。

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

    public void setNext(Node<E> next) {
        this.next = next;
    }

    public Node<E> next() {
        return this.next;
    }

    public void setFront(Node<E> front) {
        this.front = front;
    }

    public Node<E> front() {
        return this.front;
    }

    public E getValue() {
        return value;
    }

  • 定义队列类MyQueue

  1. 定义属性:头结点head、尾结点last、队列中元素个数int size、队列容量int capacity

    private Node<E> head;
    private Node<E> last;
    private int size;
    private int capacity;
  1. 定义方法:

(1)构造方法

    public MyQueue(int capacity) {
        this.size = 0;
        this.capacity = capacity;
    }

(2)put方法

把要存入队列的元素装入结点,并放到双向链表的头部。

这样,头结点的元素永远是最后存入队列的元素。

    /**
     * 
     * @param e 存入的元素
     */
    public void put(E e) {
//        判断队列是否已满
        if (size == capacity){
            throw new ArrayIndexOutOfBoundsException();
        }
        Node<E> newNode = new Node<>(e);
//        如果队列没有结点,把当前结点作为尾结点、头结点
//        如果队列有结点,将当前结点放到头结点的上方,并设置头结点为当前结点
        if (size == 0) {
            last = newNode;
        } else {
            newNode.setNext(head);
            head.setFront(newNode);
        }
        head = newNode;
        size++;
    }

(3)take方法

    /**
     * 
     * @return 取出的元素
     */
    public E take() {
//        判断队列是否为空
        if (size == 0) {
            throw new ArrayIndexOutOfBoundsException();
        }
//        尾结点中的value永远是最先存入队列的,因此取出尾结点的value
        E e = last.getValue();
//        将倒数第二个结点设置为尾结点
        last.front().setNext(null);
        last = last.front();
        size--;
        return e;
    }

(4)clear方法

    public void clear() {
        this.size = 0;
        this.head = null;
        this.last = null;
        // 中间的结点,物理上并未被删除,只是不能访问
    }

(5)其他方法

    public int size() {
        return this.size;
    }

    public int length(){
        return this.capacity;
    }

    public void setCapacity(int capacity){
        this.capacity = capacity;
    }

    public double capacityRate(){
        double capacity = this.capacity;
        double size = this.size;
        return size/capacity;
    }

    @Override
    public String toString() {
        String str = "";
        Node<E> temp = head;
        for (int i = 0; i < this.size; i++) {
            str += temp.getValue().toString();
            temp = temp.next();
        }
        return str;
    }

  • 测试

写下面这段程序简单测试一下。

public class Main {
    public static void main(String[] args) {
        MyQueue<String> myQueue = new MyQueue<>(100);
        for (int i = 0; i < 50; i++) {
            myQueue.put("x");
            System.out.println(myQueue);
            System.out.println(myQueue.size());
            System.out.println(myQueue.capacityRate());
        }
        for (int i = 0; i < 20; i++) {
            String taken = myQueue.take();
            System.out.println(taken);
            System.out.println(myQueue);
            System.out.println(myQueue.size());
            System.out.println(myQueue.capacityRate());
        }
        myQueue.clear();
        System.out.println(myQueue);
        System.out.println(myQueue.size());
        System.out.println(myQueue.capacityRate());
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值