JAVA数据结构-2.普通队列和循环队列的实现以及JAVA的Queue的使用解析

数据结构和算法

2. 队列

​ 队列是一个有序列表,可用用数组或是链表来实现.

​ 遵循先入先出的原则.

在这里插入图片描述

实现思路(普通队列)

  1. ​ 使用数组的结构来实现队列时,创建一个类,其中包含数组对象queue,同时需要maxSize来表示该队列的最大容量;
  2. 因为队列的输入和输出时分别从前后端来处理,因此需要两个变量front以及rear分别记录队列前后端的下标,front会随着数据输出而改变,rear则随着数据的输入而改变;
    1. 其中,front指向队列中队列头一个对象的前一个位置.
    2. rear指向队列尾的位置.
  3. 编写类中方法addQueue表示队列加入:
    1. 将尾指针rear向后移动:rear+1;当front==rear(队列为空).
    2. 若移动后的尾指针小于队列的最大下标maxSize-1(下标从0开始),则将数据存入rear所指的数组元素中,否则无法存入数据(rear == maxSeize-1 队列满)
  4. 编写类中方法removeQueue表示移除队列:
    1. 当队列不为空时,将头指针front移动一位,找到队列中第一个数.

代码实现(普通队列)

public class ArrayQueue {
    
    
    public  static void main(String args[]){
    
    
    }
}

class ArrayQueueClass{
    
    
    private int maxSize;
    private int front;
    private int rear;
    private int[] arr;
    public ArrayQueueClass(int arrMaxSize){
    
    
        this.maxSize = arrMaxSize;
        front = -1;
        rear = -1;
        arr = new int[arrMaxSize];
    }

    public boolean isEmpty(){
    
    
        if(front == rear){
    
    
            return true;
        }
        return false;
    }

    public boolean isFull(){
    
    
        if(rear == maxSize-1){
    
    
            return true;
        }
        return false;
    }

    public void addQueue(int data){
    
    
        if(isFull()){
    
    
            throw new RuntimeException("队列已经满了~");
        }
        rear++;
        arr[rear] = data;
    }

    public int removeQueue(){
    
    
        if(isEmpty()){
    
    
            throw  new RuntimeException("队列为空,无法取数据");
        }
        front++;
        return arr[front];
    }
    public void showQueue(){
    
    
        if(isEmpty()){
    
    
            throw  new RuntimeException("队列为空");
        }
        for (int i = front+1; i <= rear ; i++) {
    
    
            System.out.printf("%d\t",arr[i]);
        }
        System.out.println();
    }

    public int check(){
    
    
        if(isEmpty()){
    
    
            throw  new RuntimeException("队列为空");
        }

        return arr[front+1];
    }

}

问题: 指针不断增加,数组使用一次就不能使用了,没有达到复用的效果.

解决方案:将数组改为环形数组,使用取模来实现

实现思路(循环队列)

  1. front 变量的含义做一个调整, front就指向队列的第一个元素,arr[front]就是队列的第一个元素, front初始值为0
  2. rear变量的含有做一个调整, rear指向队列的最后一个元素的后一个位置,因为希望空出一个空间作为约定.此时队列的最大可使用容量为maxSize-1,rear初始值为0;
  3. 当队列满时,条件为(rear+1)%maxSize == front
  4. 当队列为空时,rear == front
  5. 队列中有效的数据个数为 (rear+maxSize -frotn)%maxSize

代码实现(循环队列)

public class CircleArrayQueueDemo {
    
    
    public  static void main(String args[]){
    
    
        CricleArrayQueue queue = new CricleArrayQueue(4);   //此时可以用队列为3
        queue.addQueue(0);
        queue.showQueue();
        queue.addQueue(1);
        queue.showQueue();
        queue.addQueue(2);
        queue.showQueue();
//        queue.addQueue(3); //java.lang.RuntimeException: 队列已经满了~  front==0  rear==3

        System.out.println(queue.removeQueue());
        queue.showQueue();
        System.out.println(queue.removeQueue());
        queue.showQueue();
        System.out.println(queue.removeQueue());
        System.out.println();
//        queue.showQueue();//java.lang.RuntimeException: 队列为空  front == rear ==3

        queue.addQueue(4);  //front ==3  rear ==0
        queue.showQueue();
        queue.addQueue(5); //front ==3  rear ==1

        System.out.println(queue.removeQueue());//front ==0  rear ==1
        System.out.println(queue.removeQueue());//front ==1  rear ==1

    }
}
class CricleArrayQueue{
    
    
    private int maxSize;
    public int front;
    public int rear;
    private int[] arr;
    public CricleArrayQueue(int arrMaxSize){
    
    
        this.maxSize = arrMaxSize;
        front = 0;  //front表示指向第一个元素 取元素时先取再+1
        rear = 0;   //rear表示指向最后一个元素的后一个位置  加元素时先加元素在+1
        arr = new int[arrMaxSize];  //设置队列最大长度,此时保留一个位置作为队列满的判断,因此最大可用数量为maxSize-1
    }
    public boolean isEmpty(){
    
    
        if(front == rear){
    
    
            return true;
        }
        return false;
    }

    public boolean isFull(){
    
    
        if((rear+1)%maxSize == front){
    
    
            return true;
        }
        return false;
    }
    public void addQueue(int data){
    
    
        if(isFull()){
    
    
            throw new RuntimeException("队列已经满了~");
        }
        arr[rear] = data;
        rear = (rear+1)%maxSize;
    }
    public int removeQueue(){
    
    
        if(isEmpty()){
    
    
            throw  new RuntimeException("队列为空,无法取数据");
        }
        int value = arr[front];
        front = (front+1)%maxSize;
        return value;
    }
    public void showQueue(){
    
    
        if(isEmpty()){
    
    
            throw  new RuntimeException("队列为空");
        }
        for (int i = front; i < front+ (rear - front + maxSize)%maxSize; i++) {
    
    
            System.out.printf("%d\tarr[%d]",i%maxSize,arr[i%maxSize]);
            System.out.println();
        }
        System.out.println();
    }
    public int check(){
    
    
        if(isEmpty()){
    
    
            throw  new RuntimeException("队列为空");
        }
        return arr[front];
    }

}

JAVA中的队列类Queue

在java的高级数据类型中,LinkedList类实现了Queue接口,因此我们可以把LinkedList当成Queue来用.
LinkedList 会在双向链表数据结构章节补充源码解析.

public class javaQueue {
    
    
    public  static void main(String args[]){
    
    
        //add()和remove()方法在失败的时候会抛出异常(不推荐)
        Queue<String> queue = new LinkedList<String>();
        //添加元素
        queue.offer("a");
        queue.offer("b");
        queue.offer("c");
        queue.offer("d");
        queue.offer("e");
        for(String q : queue){
    
    
            System.out.println(q);
        }
        System.out.println("===");
        System.out.println("poll="+queue.poll()); //返回第一个元素,并在队列中删除
        for(String q : queue){
    
    
            System.out.println(q);
        }
        System.out.println("===");
        System.out.println("element="+queue.element()); //返回第一个元素
        for(String q : queue){
    
    
            System.out.println(q);
        }
        System.out.println("===");
        System.out.println("peek="+queue.peek()); //返回第一个元素
        for(String q : queue){
    
    
            System.out.println(q);
        }
    }
}

offer,add 区别:

  • 一些队列有大小限制,因此如果想在一个满的队列中加入一个新项,多出的项就会被拒绝。
  • 这时新的 offer 方法就可以起作用了。它不是对调用 add() 方法抛出一个 unchecked 异常,而只是得到由 offer() 返回的 false。
    poll,remove 区别:
  • remove() 和 poll() 方法都是从队列中删除第一个元素。remove() 的行为与 Collection 接口的版本相似, 但是新的 poll() 方法在用空集合调用时不是抛出异常,只是返回 null。因此新的方法更适合容易出现异常条件的情况。
    peek,element区别:
  • element() 和 peek() 用于在队列的头部查询元素。与 remove() 方法类似,在队列为空时, element() 抛出一个异常,而 peek() 返回 null。

猜你喜欢

转载自blog.csdn.net/weixin_44634197/article/details/108308221