数据结构(二)---队列

队列

手写队列

public class ArrayQueueDemo01 {
    public static void main(String[] args) {
        //测试一下手写的队列
        ArrayQueue arrayQueue = new ArrayQueue(3);//利用构造器创建一个长度为3的队列
        char key = ' ';//接收用户的输入
        Scanner scanner = new Scanner(System.in);//拿到一个输入的扫描器
        boolean loop = true;

        //输出一个操作的菜单
        while (loop) {
            System.out.println("s(show):显示队列");
            System.out.println("e(exit):退出程序");
            System.out.println("a(add):添加数据到队列");
            System.out.println("g(get):从队列取出数据");
            System.out.println("h(head):显示队列头部");
            System.out.println("r(rear):显示队列尾部");
            key = scanner.next().charAt(0);//接收一下用户输入的内容字符

            //来一个枚举switch
            switch (key) {
                case 's':
                    arrayQueue.showQueue();
                    break;

                case 'a':
                    System.out.println("请输入要添加的数");
                    int value = scanner.nextInt();
                    arrayQueue.addQueue(value);
                    break;

                case 'g'://取数据的时候可能会出现异常,需要try catch处理
                    try {
                        int res=arrayQueue.getQueue();
                        System.out.println("出队的数据为:"+res);
                    } catch (Exception e){
                        System.out.println(e.getMessage());
                    }

                    break;

                case 'h':
                    try {
                        int res=arrayQueue.headQueue();
                        System.out.println("头部的数据为:"+res);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;

                case 'r':
                    try {
                        int res=arrayQueue.rearQueue();
                        System.out.println("尾部的数据为:"+res);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;

                case 'e':
                    scanner.close();
                    loop=false;
                    break;

                default:
                    break;
            }
        }
        System.out.println("程序退出");

    }
}

数组模拟队列

//使用数组模拟队列
class ArrayQueue {
    private int maxSize;//数组的最大容量
    private int front;//队列的头指针
    private int rear;//队列的尾指针
    private int[] arr;//这个数组用来存放数据,模拟队列

    //创建队列的构造器
    public ArrayQueue(int arrMaxSize) {
        maxSize = arrMaxSize;
        arr = new int[maxSize];
        front = -1;//front指针初始化时是指向队列头的前一个位置,表示为空
        rear = -1;//rear指针初始化时是指向队列尾的当时位置(也就是队列的最后一个位置)

    }

    //(1)判断队列是不是满的
    public boolean isFull() {
        return rear == maxSize - 1;//如果想等就说明队列已经满了
    }

    //(2)判断队列是不是空的
    public boolean isEmpty() {
        return rear == front;//如果想等就说明队列已经空了
    }

    //(3)添加数据到队列(首先要判断队列是不是满的)
    public void addQueue(int n) {
        //判断队列是不是满了
        if (isFull()) {
            System.out.println("队列已经满了,无法添加");
            return;
        } else {
            rear++;//rear随着添加的数据一起移动
            arr[rear] = n;//rear后移一位,然后把新添加的数据放到rear指的位置
        }
    }

    //(4)获取队列的数据(也就是数据出队列)
    public int getQueue() {
        //先判断队列是不是空的
        if (isEmpty()) {
            //通过抛出异常来处理结果,不用写return
            throw new RuntimeException("队列是空的,无法取得");
        } else {
            front++;//取出数据的时候,头指针往后移,然后多出来的那个数据就是出队的
            return arr[front];
        }
    }

    //(5)显示队列的全部数据(就是一个简单的遍历数组)
    public void showQueue() {
        //遍历数组arr
        if (isEmpty()) {
            System.out.println("队列为空,没有数据");
            return;
        } else {
            for (int i = 0; i < arr.length; i++) {
                System.out.printf("arr[%d]=%d\n", i, arr[i]);
            }
        }
    }

    //(6)显示队列的头数据,注意不是取数据,知识显示出来而已
    public int headQueue() {
        //判断是否为空
        if (isEmpty()) {
            throw new RuntimeException("队列为空,没有数据");
        } else {
            //直接返回头指针指向额数据
            return arr[front + 1];
        }
    }

    //(7)显示队列的尾数据,注意不是取数据,知识显示出来而已
    public int rearQueue() {
        //判断是否为空
        if (isEmpty()) {
            throw new RuntimeException("队列为空,没有数据");
        } else {
            //直接返回头指针指向额数据
            return arr[rear];
        }
    }
}

优化成环形数组

1)目前数组使用一次就不能用,没有达到复用的效果
2)把这个数组使用算法,改进成一个环形的数组,也就是数组模拟环形队列

思路如下:
1.front变量的含义做一个调整:front就指向队列的第一个元素,也就是说arr[front]就是队列的第一个元素
front的初始值=0
2.rear变量的含义做一个调整:rear就指向队列的最后一个元素,因为我希望空出一个空间作为约定
rear的初始值=0
3.当队列满了,条件是:(rear+1)%maxSize=front(队列满的时候,rear就在front后面)
4.当队列为空,条件是:rear==front(队列空的时候,rear和front在一起)
5.当我们这样分析,队列中有效的数据的个数:(rear+maxSize-front)%maxSize
6.我们就可以在原来得队列上进行修改,得到一个环形队列

public class CircleArrayQueueDemo02 {
    public static void main(String[] args) {
        //测试一下手写的队列,写的大小为4,其实只有3,因为有一个要作为空区间
        CircleArrayQueue arrayQueue = new CircleArrayQueue(4);//利用构造器创建一个长度为3的队列
        char key = ' ';//接收用户的输入
        Scanner scanner = new Scanner(System.in);//拿到一个输入的扫描器
        boolean loop = true;

        //输出一个操作的菜单
        while (loop) {
            System.out.println("s(show):显示队列");
            System.out.println("e(exit):退出程序");
            System.out.println("a(add):添加数据到队列");
            System.out.println("g(get):从队列取出数据");
            System.out.println("h(head):显示队列头部");
            System.out.println("r(rear):显示队列尾部");
            key = scanner.next().charAt(0);//接收一下用户输入的内容字符

            //来一个枚举switch
            switch (key) {
                case 's':
                    arrayQueue.showQueue();
                    break;

                case 'a':
                    System.out.println("请输入要添加的数");
                    int value = scanner.nextInt();
                    arrayQueue.addQueue(value);
                    break;

                case 'g'://取数据的时候可能会出现异常,需要try catch处理
                    try {
                        int res=arrayQueue.getQueue();
                        System.out.println("出队的数据为:"+res);
                    } catch (Exception e){
                        System.out.println(e.getMessage());
                    }

                    break;

                case 'h':
                    try {
                        int res=arrayQueue.headQueue();
                        System.out.println("头部的数据为:"+res);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;

                case 'r':
                    try {
                        int res=arrayQueue.rearQueue();
                        System.out.println("尾部的数据为:"+res);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;

                case 'e':
                    scanner.close();
                    loop=false;
                    break;

                default:
                    break;
            }
        }
        System.out.println("程序退出");

    }
}

数组模拟队列

class CircleArrayQueue {
    private int maxSize;//数组的最大容量

    //front变量的含义做一个调整:front就指向队列的第一个元素,也就是说arr[front]就是队列的第一个元素
    //front的初始值=0
    private int front;//队列的头指针

    //rear变量的含义做一个调整:rear就指向队列的最后一个元素,因为我希望空出一个空间作为约定
    //rear的初始值=0
    private int rear;//队列的尾指针

    private int[] arr;//这个数组用来存放数据,模拟队列

    //创建队列的构造器
    public CircleArrayQueue(int arrMaxSize) {
        maxSize = arrMaxSize;
        arr = new int[maxSize];
        front = 0;//front指针初始化时是指向队列头的前一个位置,表示为空
        rear = 0;//rear指针初始化时是指向队列尾的当时位置(也就是队列的最后一个位置)

    }

    //(1)判断队列是不是满的
    public boolean isFull() {
        return (rear+1)%maxSize==front;//如果想等就说明队列已经满了
    }

    //(2)判断队列是不是空的
    public boolean isEmpty() {
        return rear == front;//如果想等就说明队列已经空了
    }

    //(3)添加数据到队列(首先要判断队列是不是满的)
    public void addQueue(int n) {
        //判断队列是不是满了
        if (isFull()) {
            System.out.println("队列已经满了,无法添加");
            return;
        } else {
            //!!!!!!直接把数据加入!!!!!!!!
            arr[rear]=n;
            //把rear后移,这里必须考虑取模
            //本来rear到底就满了结束,但是有了取模,就可以让rear重新从0开始,达到循环的目的
            rear=(rear+1)%maxSize;
        }
    }

    //(4)获取队列的数据(也就是数据出队列)
    public int getQueue() {
        //先判断队列是不是空的
        if (isEmpty()) {
            //通过抛出异常来处理结果,不用写return
            throw new RuntimeException("队列是空的,无法取得");
        } else {
            //首先,要分析出来front是指向队列的第一个元素
            //1.先把front对应的值保留到一个临时变量
            //2.把front后移
            //3.把临时保存的变量返回
            int value=arr[front];
            front=(front+1)%maxSize;
            return value;
        }
    }

    //(5)显示队列的全部数据(就是一个简单的遍历数组)
    public void showQueue() {
        //遍历数组arr
        if (isEmpty()) {
            System.out.println("队列为空,没有数据");
            return;
        } else {
            //思路:从front开始遍历,遍历多少个元素
            //这个地方需要动脑筋
            for (int i = front; i < front+size(); i++) {
                System.out.printf("arr[%d]=%d\n", i%maxSize, arr[i%maxSize]);
            }
        }
    }

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

    //(6)显示队列的头数据,注意不是取数据,知识显示出来而已
    public int headQueue() {
        //判断是否为空
        if (isEmpty()) {
            throw new RuntimeException("队列为空,没有数据");
        } else {
            //直接返回头指针指向额数据
            return arr[front];
        }
    }

    //(7)显示队列的尾数据,注意不是取数据,知识显示出来而已
    public int rearQueue() {
        //判断是否为空
        if (isEmpty()) {
            throw new RuntimeException("队列为空,没有数据");
        } else {
            //直接返回头指针指向额数据
            return arr[rear];
        }
    }
}
发布了41 篇原创文章 · 获赞 5 · 访问量 656

猜你喜欢

转载自blog.csdn.net/weixin_44823875/article/details/104930932
今日推荐