数据结构与算法---队列

队列概述

数组模拟队列

数组模拟环形队列

队列正如其名-排队站列。生活中随处可见,食堂买饭、银行取钱、地铁买票....我们会发现这些事情有一个共同的特点:先进先出
这也就是队列的特点。

队列概述:

队列是一个有序列表,可以用数组或是链表实现。遵循先进先出,即先存入队列的数据,要先取出。后存入的要后取出。那么就说明向队列中加数据是在尾部加,取数据是从顶部取。

数组模拟队列:

1、首先我们要明白队列是个有序列表,输出输入 分别要从 前后 端来处理的。
2、将数据存入队列时,我们要注意 :
① 尾指针rear+1,当首指针 front== rear时,队列为空。
②若rear<队列最大下标maxSize-1,可存入数据。当rear==maxSize-1,说明队列满了。
③front是指向队列头部的前一个位置,rear指向队列尾部就是最后一个位置。
 

 数组模拟实现队列的代码:

package com.datestructures;

import java.util.Scanner;

public class ArrayQueueDemo {
    public static void main(String[] args) {
        //创建队列对象
    ArrayQueue arrayQueue = new ArrayQueue(3);
    char key = ' '; //接收用户输入
    Scanner scanner = new Scanner(System.in);
    boolean loop = true;
    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':
                arrayQueue.showQueue();
                break;
            case 'a':
                System.out.println("输入要添加的数据:");
                int input = scanner.nextInt();
                arrayQueue.addQueue(input);
                break;
            case'g':
                try {
                    System.out.println("取出的数据是");
                    int ret = arrayQueue.getQueue();
                    System.out.println(ret);
                    break;
                } catch (Exception e) {
                    System.out.println(e.getMessage());
                }
            case'h':
                try {
                   int ret = arrayQueue.headQueue();
                    System.out.println("队列头部是");
                    System.out.println(ret);
                    break;
                } catch (Exception e) {
                    System.out.println(e.getMessage());
                }
            case'e':
                scanner.close();
                loop = false;
                break;
        }
    }

    }
}

class ArrayQueue {
    private int maxSize; //表示数组的最大长度
    private int rear; // 数组指针尾
    private int front;  //数组指针头
    int[] arr; //存放数据模拟队列
    public ArrayQueue(int arrMaxSize) {  //创建队列构造器
        maxSize = arrMaxSize;
        rear = -1;
        front = -1;
        arr = new int[maxSize];
    }
    public boolean isFull() {  //判断队列是否为满
        return rear == maxSize-1;
    }

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

    public void addQueue(int n) { //添加数据到队列
        if (isFull()) {
            System.out.println("队列已满,无法添加");
            return;
        }
        rear++;
        arr[rear] = n;
    }

    public int getQueue() { //获取队列的数据,出队列
        if (isEmpty()) {
            throw new RuntimeException("队列已空,无法删除");
        }
        front++;
        return arr[front];
    }

    public void showQueue() { //显示队列的所有数据
        if (isEmpty()) {
            System.out.println("队列为空,不能显示");
            return;
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.printf("a[%d] = %d\n",i,arr[i]);
        }
    }
    public int headQueue() { //显示队列头部
        if (isEmpty()) {
            throw new RuntimeException("队列为空");
        }
        return arr[front+1];
    }


}

我们会发现:目前数组用一次就不能用了,没有达到复用的效果。将这个数组使用算法改进为环形数组。

数组模拟环形队列:

1、使front指向队列的第一个元素,即arr[font]就是队列的第一个元素。 front初始值为0
2、使rear指向队列的最后一个元素的后一个位置。 rear的初始值也为0
3、当队列满时 (rear+1)%maxSize = front
4、当队列空时 rear=front 
5、队列中有效元素个数(rear + maxSize - front) % maxSize   //rear=1  front=0

class CircleArray {
    private int maxSize; //表示数组的最大长度
    private int rear; // 数组指针尾
    private int front;  //数组指针头
    int[] arr; //存放数据模拟队列

    public CircleArray(int arrMaxSize) {
        maxSize = arrMaxSize;
        arr = new int[maxSize];
        front = 0;
        rear = 0;
    }

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

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

    //添加数据到队列
    public void addQueue(int n) {
        //判断数列是否为满
        if (isFull()) {
            System.out.println("队列已满,无法添加");
            return;
        }
        //直接将数据加入
        arr[rear] = n;
        //将rear后移
        rear = (rear + 1) % maxSize;
    }

    //获取队列的数据,出队列
    public int getQueue() {
        if (isEmpty()) {
            throw new RuntimeException("队列已空,无法删除");
        }
        //这里需要分析出front是指向队列的第一个元素
        //1、先把front对应的值先保存在一个临时变量
        //2、将front后移,考虑取模
        //3、将临时保存的变量返回
        int value = arr[front];
        front = (front + 1) % maxSize;
        return value;
    }

    //显示队列的所有数据
    public void showQueue() {
        if (isEmpty()) {
            System.out.println("队列为空,不能显示");
            return;
        }
        //从front开始遍历,遍历多少个元素
        for (int i = front; i < front + size(); i++) {
            System.out.printf("a[%d] = %d\n", i % maxSize, arr[i % maxSize]);
        }
    }

    //求出当前队列有效个数
    public int size() {
        return (rear + maxSize - front) % maxSize;
    }

    //显示队列头部
    public int headQueue() {
        if (isEmpty()) {
            throw new RuntimeException("队列为空");
        }
        return arr[front];
    }
}
发布了51 篇原创文章 · 获赞 14 · 访问量 2327

猜你喜欢

转载自blog.csdn.net/qq_41185460/article/details/102680689