队列(一)

228 阅读4分钟

队列(数组模拟)

队列概念

  队列是一种特殊的线性表,只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作(先进先出特点)。进行插入操作的端称为队尾,进行删除操作的端称为队头。

数组模拟队列

  使用一个数组模拟队列。数组的长度即为队列的最大容量,设置front和rear代表队列的队头和队尾,初始值均设为-1。front指向队列中第一个元素的前一个位置,rear指向队列中最后一个元素。队列为空的条件为rear == front,队列为满的条件是rear == maxSize - 1;

顺序队列代码实现(java)

package com.arrayqueue;

import java.util.Scanner;

public class ArrayQueue {
    public static void main(String[] args) throws Exception {
        //创建一个队列
        Queue arrQueue = new Queue(3);
        boolean loop = true;
        char key;
        Scanner scanner = new Scanner(System.in);
        while (loop) {
            System.out.println("s:显示队列");
            System.out.println("e:退出程序");
            System.out.println("a:添加数据");
            System.out.println("g:获取数据");
            System.out.println("h:查看队列头数据");
            key = scanner.next().charAt(0);
            switch (key) {
                case 's':
                    System.out.println("队列为:");
                    arrQueue.showQueue();
                    break;
                case 'a':
                    int addValue;
                    System.out.println("请输入一个数:");
                    addValue = scanner.nextInt();
                    arrQueue.addQueue(addValue);
                    break;
                case 'g':
                    try {
                        int getValue = arrQueue.getQueue();
                        System.out.printf("取出的数据是:%d\n", getValue);
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'h':
                    try {
                        int headValue = arrQueue.headQueue();
                        System.out.printf("队列头的数据是:%d\n", headValue);
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'e':
                    loop = false;
                    System.out.println("程序退出!");
                    break;
            }
        }
    }
}

class Queue {
    private int maxSize;
    //front 指向队列的第一个元素的前一个位置
    private int front;
    //rear 指向队列最后一个元素
    private int rear;
    private int[] arr;

    public Queue(int arrMaxSize) {
        maxSize = arrMaxSize;
        arr = new int[maxSize];
        front = -1;
        rear = -1;
    }

    public boolean isEmpty() {
        //判断队列是否为空
        return front == rear;
    }

    public boolean isFull() {
        //判断队列是否满
        return rear == maxSize - 1;
    }

    public void addQueue(int value) {
        //向队列中添加元素
        if (isFull()) {
            System.out.println("队列已满!!!");
            return;
        }
        rear++;
        arr[rear] = value;
    }

    public int getQueue() {
        //取出队列中的第一个元素
        if (isEmpty()) {
            throw new RuntimeException("队列中无元素!!!");
        }
        front++;
        return arr[front];
    }

    public void showQueue() {
        //展示队列
        if (isEmpty()){
            System.out.println("队列为空!!!");
            return;
        }
        for (int i = front; i < rear; i++) {
            System.out.printf("arr[%d] = %d\n", i + 1, arr[i + 1]);
        }
    }

    public int headQueue() {
        //查看队列中的头元素
        if (isEmpty()) {
            throw new RuntimeException("队列中无元素!!!");
        }
        return arr[front + 1];
    }
}

数组模拟队列的缺点

  数组只能使用一次,当第一次插入的值被全部删除后,此时的队列不可插入新的队尾元素,否则会出现溢出现象,即因数组越界而导致程序非法操作错误,但其实队列并未占满,为了解决这种假溢出现象,提出了数组模拟循环队列。

数组模拟循环队列

  队列的最大容量为数组长度-1,这是为了防止循环队列中判断队列为空和队列未满条件相同而做出的约定,设置front和rear代表队列的队头和队尾,初始值均设为0。front指向队列中第一个元素,rear指向队列中最后一个元素的后一个位置。此时队列为空的条件与顺序队列一致,而队列为满的条件则为(rear + 1) % maxSize == front;取模实现了循环的目的。并且在每次插入、删除操作时都要对rearfront进行取模运算防止越界。

循环队列代码实现(java)

package com.arrayqueue;

import java.util.Scanner;

public class LoopArrayQueue {
    public static void main(String[] args) throws Exception {
        //创建一个队列
        LoopQueue loopArrQueue = new LoopQueue(3);
        boolean loop = true;
        char key;
        Scanner scanner = new Scanner(System.in);

        while (loop) {
            System.out.println("s:显示队列");
            System.out.println("e:退出程序");
            System.out.println("a:添加数据");
            System.out.println("g:获取数据");
            System.out.println("h:查看队列头数据");
            key = scanner.next().charAt(0);
            switch (key) {
                case 's':
                    System.out.println("队列为:");
                    loopArrQueue.showQueue();
                    break;
                case 'a':
                    int addValue;
                    System.out.println("请输入一个数:");
                    addValue = scanner.nextInt();
                    loopArrQueue.addQueue(addValue);
                    break;
                case 'g':
                    try {
                        int getValue = loopArrQueue.getQueue();
                        System.out.printf("取出的数据是:%d\n", getValue);
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'h':
                    try {
                        int headValue = loopArrQueue.headQueue();
                        System.out.printf("队列头的数据是:%d\n", headValue);
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'e':
                    loop = false;
                    System.out.println("程序退出!");
                    break;
            }
        }
    }
}

class LoopQueue {
    private int maxSize;
    //front 指向队列的第一个元素
    private int front;
    //rear 指向队列最后一个元素的后一个位置
    private int rear;
    //该模拟数组中队列的实际最大长度为数组长度-1
    private int[] arr;

    public LoopQueue(int arrMaxSize) {
        maxSize = arrMaxSize;
        arr = new int[maxSize];
        System.out.printf("队列最大长度为:%d\n", maxSize - 1);
    }

    public boolean isEmpty() {
        //判断队列是否为空
        return front == rear;
    }

    public boolean isFull() {
        //判断队列是否满
        return (rear + 1) % maxSize == front;
    }

    public void addQueue(int value) {
        //向队列中添加元素
        if (isFull()) {
            System.out.println("队列已满!!!");
            return;
        }
        arr[rear] = value;
        rear = (rear + 1) % maxSize;
    }

    public int getQueue() {
        //取出队列中的第一个元素
        if (isEmpty()) {
            throw new RuntimeException("队列中无元素!!!");
        }
        int flag = front;
        front = (front + 1) % maxSize;
        return arr[flag];
    }

    public void showQueue() {
        //展示队列
        if (isEmpty()) {
            System.out.println("队列为空!!!");
            return;
        }
        for (int i = front; i < front + queueSize(); i++) {
            System.out.printf("arr[%d] = %d\n", i % maxSize, arr[i % maxSize]);
        }
    }

    public int headQueue() {
        //查看队列中的头元素
        if (isEmpty()) {
            throw new RuntimeException("队列中无元素!!!");
        }
        return arr[front];
    }

    public int queueSize() {
        return (rear - front + maxSize) % maxSize;
    }
}