【笔记】数据结构与算法——队列

Ø队列

队列介绍
  • 概念:队列是一个有序列表,可以用数组或是链表来实现

  • 原则:先入先出;即:先存入队列的数据,要先取出,后存入的要后取出

  • 示意图:(使用数组模拟队列示意图)
    - [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4tdwKbTi-1596870792947)(D:\Typora\img\队列.jpg)]

1.数组模拟队列
1)队列数组声明:
  • maxSize表示队列的最大容量

  • front记录队列前端的下标,rear记录队列后端的下标;front会随着数据输出而改变,而rear是随着数据输入而改变

  • 向队列添加数据时:

    • 将尾指针后移:rear+1,当front=rear ==>队列为
    • rear<maxSize-1,则存入数据;否则无法存入。当rear==maxSize-1==>队列已
2)代码实现:
package com.queue;
/*
@author qw
@date 2020/7/17 - 21:03
**/

import java.util.Scanner;

public class ArrayQueueDemo {
    public static void main(String[] args) {
        //创建队列
        ArrayQueue arrayQueue = new ArrayQueue(3);
        char ch = ' ';//接收用户输入
        Scanner sc = 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):查看队列头的数据");
            ch=sc.next().charAt(0);//接收一个字符
            switch (ch){
                case 's'://显示队列
                    arrayQueue.showQueue();
                    break;
                case 'a'://向队列添加数据
                    System.out.println("请输入需要添加的数据:");
                    int value=sc.nextInt();
                    arrayQueue.addQueue(value);
                    break;
                case 'g'://从队列取出数据
                    try {
                        int result= arrayQueue.getQueue();
                        System.out.println("取出的数据是"+result);
                    }catch (Exception e){
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'h'://查看队列头的数据
                    try {
                        int result=arrayQueue.headQueue();
                        System.out.println("取出队列头数据是"+result);
                    }catch (Exception e){
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'e'://退出
                    sc.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;//指向队列头部,为队列头的前一个位置
        rear=-1;//指向队列尾部,为队列最后一个数据
    }

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

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

    //向队列添加数据,入队
    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.println("arr["+i+"]="+arr[i]);
        }
    }

    //显示队列头数据
    public int headQueue(){
        if(isEmpty()){
            throw new RuntimeException("队列为空,没有数据。");
        }
        return arr[front+1];
    }
}
3)问题分析并优化:
  • 目前数组使用一次就不能再用,没有达到复用的效果
  • 将这个数组使用算法,该进成一个环形的队列 取模:%
2.数组模拟环形队列
1)分析:
  • 尾索引的下一个为头索引时表示队列已满,即将队列容量空出一个作为约定,这个在做判断队列满时注意 (rear+1)%maxSize===front —> 满
  • rear==front —> 空
2)思路:
  • front指向队列的第一个元素,即arr[front]为队列的第一个元素。front的初始值=0
  • rear指向队列的最后一个元素的后一个位置,为了空出一个位置作为约定。rear的初始值=0
  • 当队列时,(rear+1)%maxSize==front
  • 当队列为时,rear==front
  • 队列中有效数据的个数为:(rear + maxSize - front) % maxSize
  • 以上,即可在原来的队列基础上,修改得到一个环形队列。
3)代码实现:
package com.queue;
/*
@author qw
@date 2020/7/20 - 22:05
**/

import java.util.Scanner;

public class CircleArrayQueueDemo {
    public static void main(String[] args) {
        //创建队列
        CircleArray circleArray = new CircleArray(4);//队列数据最多3个
        char ch = ' ';//接收用户输入
        Scanner sc = 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):查看队列头的数据");
            ch=sc.next().charAt(0);//接收一个字符
            switch (ch){
                case 's'://显示队列
                   circleArray.showQueue();
                    break;
                case 'a'://向队列添加数据
                    System.out.println("请输入需要添加的数据:");
                    int value=sc.nextInt();
                    circleArray.addQueue(value);
                    break;
                case 'g'://从队列取出数据
                    try {
                        int result= circleArray.getQueue();
                        System.out.println("取出的数据是"+result);
                    }catch (Exception e){
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'h'://查看队列头的数据
                    try {
                        int result=circleArray.headQueue();
                        System.out.println("取出队列头数据是"+result);
                    }catch (Exception e){
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'e'://退出
                    sc.close();
                    loop=false;
                    break;
                default:
                    break;
            }
        }
        System.out.println("程序退出。");
    }
}


class CircleArray{
    private int maxSize;//数组最大容量
    //front指向队列的第一个元素,即arr[front]为队列的第一个元素。
    // front的初始值=0
    private int front;//队列头
    //rear指向队列的最后一个元素的**后一个位置**,为了空出一个位置作为约定。
    //rear的初始值=0
    private int rear;//队列尾
    private int[] arr;//该数组用于存放数据,模拟队列

    public CircleArray(int arrMaxSize){
        maxSize=arrMaxSize;
        arr=new int[maxSize];

    }

    //判断队列是否已满
    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+1)%maxSize;//尾指针后移,环形队列需要取模
    }

    //从队列获取数据,出队
    public int getQueue(){
        //判断队列是否为空
        if(isEmpty()){
            throw new RuntimeException("队列为空,不能取数据。");
        }
        //将front对应的值保存在一个临时变量temp中
        int temp=arr[front];
        //将front后移,考虑取模
        front=(front+1)%maxSize;
        //返回临时变量
        return temp;
    }

    //遍历队列
    public void showQueue(){
        if(isEmpty()){
            System.out.println("队列为空,没有数据。");
            return;
        }
        //从front开始遍历,遍历有效个数
        for(int i=front;i<front+size();i++){
            System.out.println("arr["+(i%maxSize)+"]="+arr[i%maxSize]);
        }
    }

    //求出当前队列有效数据的个数
    public int size(){
        return (rear+maxSize-front)%maxSize;
    }
    //显示队列头数据
    public int headQueue(){
        if(isEmpty()){
            throw new RuntimeException("队列为空,没有数据。");
        }
        return arr[front];
    }

}

学习视频——b站尚硅谷

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值