【算法02】数组模拟队列(一次性&&循环)

1、何为队列?

队列是一个有序列表,可以用数组or链表来实现。跟排队一样,先入先出,即:先存入队列的数据先取出,后存入的数据后取出

 2、一次性的队列代码示例

public class suanfa {
    //一次性队列问题
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        duilie dl = new duilie(3);
        System.out.println("请输入您想进行的操作:\n" +
                "1、显示队列所有元素\n" +
                "2、取出队列的数据\n" +
                "3、向队列中添加数据\n" +
                "4、显示头数据\n" +
                "5、退出系统");
        boolean flag = true;
        while(flag){
            int i = in.nextInt();
//一定要注意这句话放在循环内部!!不然就输入一个数后一直操作此数据对应的功能了!
            switch(i){
                case 1:
                    dl.getall();
                    break;
                case 2:
                    dl.get();
                    break;
                case 3:
                    System.out.println("请输入你想添加的数据:");
                    int l = in.nextInt();
                    dl.add(l);
                    break;
                case 4:
                    dl.showhead();
                    break;
                case 5:
                    in.close();
                    flag = false;
                    System.out.println("程序已退出!");
                    break;
                default:
                    break;
            }
        }
    }
}
class duilie{
    //队列的生成
    private int maxsize;//队列数组最长长度
    private int front;//头结点
    private int rear;//尾结点
    int []arry;//定义队列数组

    public duilie(int max){
        maxsize = max;
        front = -1;
        rear = -1;
        arry = new int[maxsize];
    }
    //判断队列是否为空
    public boolean isempty(){
        if(front == rear){
            return true;
        }
        else {
            return false;
        }
    }
    //判断队列是否已满
    public boolean isfull(){
        if(rear == (maxsize - 1)){
            return true;
        }else{
            return false;
        }
    }
    //添加数据
    public void add(int n){
        if(isfull()){
            System.out.println("数据已满!");
        }else{
            rear++;
            arry[rear] = n;
            System.out.println("添加成功!");
        }
    }
    //取出队列的数据值(下段代码并没有将数据取出来,只是把front指针后移了)
    public void get(){
        if(isempty()){
            System.out.println("队列中没有数据!");
        }else{
            front++;
            System.out.println("取出的数据为:" + arry[front]);
        }
    }
    //获取队列的所有数据值
    public void getall(){
        if(isempty()){
            System.out.println("队列中没有数据!");
        }else{
            for(int i = 0;i < arry.length;i++){
                System.out.print("第" + (i + 1) + "个数值为:" + arry[i] + "\n");
            }
        }
    }
    //显示队列的头数据
    public void showhead(){
        if(isempty()){
            System.out.println("队列中没有数据!");
        }else{
            front++;
            System.out.println("队列的头数据为:" + arry[front]);
        }
    }
}

3、一次性队列的问题分析及优化

1>目前数组使用一次就不能用,没有达到复用的效果。详情参见代码中:取出队列的数据值,即get()方法,只是指针后移,但是数据并没有删除,空间依旧被占用着。

2>将这个数组使用算法,改进成一个环形的%
 

碎碎念:看到弹幕上的这些话要笑喷了🤣你以为老师错了,实际上老师站在大气层在教你🤣

4、循环队列

1>front变量的含义调整为:front指向队列的第一个元素,即front的初始值为0,arry[front]就是队列的第一个元素

2>rear变量的含义调整为:rear指向队列最后一个元素的后一个位置,且rear指向的位置元素为空,便于判断队列满or空

3>元素进队后rear所在位置:rear = (rear + 1)% maxsize

4>队满的条件为:(rear + 1)% maxsize == front

5>队空的条件为:rear == front

6>队列中有效的数据个数为:有效个数为:(rear + maxsize - front)% maxsize

对<6>进行解析:

当rear > front时,可以理解为:

则有效数据的个数即为数轴上front和rear之间的长度,又由于rear指向的是一个空数据的空间,故长度为:(rear - 1)- front + 1,化简得:rear - front 

当rear < front时,可以理解为:

此时rear - front 为负数,也就是没有存数据的空间量,则与maxsize相加后得到的就是队列中真正的数据量了,即:(rear - front + maxsize)% maxsize

5、循环队列的分析

假设H还未入队,则rear指向H所在处。

 

当H入队,则rear的位置应该为:(7 + 1)% maxsize,其中maxsize为8,则结果为0,故rear指向0号位置。

同理,I入队。

此时若不留出一个空位置,则再进入一个数据时,rear == front代表队满,而当队空时也满足此条件,所以采取这种方式的话,需要另设一个标识符或者count统计,太麻烦了,于是我们采取少用一个元素空间的方法。

3.6 循环队列_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1xQ4y1r7KS/?spm_id_from=333.337.search-card.all.click&vd_source=ecf4621f38f52d03ce016112854a3efb

▲以上视频对我帮助较大

6、循环队列代码

public class suanfa_02 {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        CirleDuilie dl = new CirleDuilie(4);//设置数组长度为4,有效数据长度最大为3
        System.out.println("请输入您想进行的操作:\n" +
                "1、显示队列所有元素\n" +
                "2、取出队列的数据\n" +
                "3、向队列中添加数据\n" +
                "4、显示头数据\n" +
                "5、退出系统");
        boolean flag = true;
        while(flag){
            int i = in.nextInt();
            switch(i){
                case 1:
                    dl.getall();
                    break;
                case 2:
                    dl.get();
                    break;
                case 3:
                    System.out.println("请输入你想添加的数据:");
                    int l = in.nextInt();
                    dl.add(l);
                    break;
                case 4:
                    dl.showhead();
                    break;
                case 5:
                    in.close();
                    flag = false;
                    System.out.println("程序已退出!");
                    break;
                default:
                    break;
            }
        }
    }
}
class CirleDuilie{
    //循环队列的生成
    private int maxsize;//循环队列的长度
    private int front;//头结点,若不赋值,则int类型的变量默认为0
    private int rear;//尾结点,若不赋值,则int类型的变量默认为0
    private int []arry;//定义队列数组
    public CirleDuilie(int max){
        maxsize = max;
        arry = new int[maxsize];
    }
    //判断循环队列是否为空
    public boolean isempty(){
        return front == rear;
    }
    //判断队列是否已满
    public boolean isfull(){
        return front == (rear + 1) % maxsize;
    }
    //添加数据
    public void add(int n){
        if(isfull()){
            System.out.println("数据已满!");
        }else{
            arry[rear] = n;
            rear = (rear + 1) % maxsize;
            System.out.println("添加成功!");
        }
    }
    //取出循环队列的数据值
    public void get(){
        if(isempty()){
            System.out.println("队列中没有数据!");
        }else{
            System.out.println("取出的数据为:" + arry[front]);
            front = (front + 1) % maxsize;
        }
    }
    //获取循环队列的有效数据长度
    public int getlength(){
        return (rear - front + maxsize) % maxsize;
    }
    //显示队列的所有数据值
    public void getall(){
        if(isempty()){
            System.out.println("队列中没有数据!");
        }else{
            //让循环队列进行有效循环,循环长度可以采取:从起始开始,延伸了有效数据个数的长度
            for(int i = front;i < front + getlength();i++){
                //这里一定要注意,输出的数据在数组中的位置要%maxsize!!
                System.out.print("第" + (i % maxsize) + "个数值为:" + arry[i % maxsize] + "\n");
            }
        }
    }
    //显示循环队列的头数据
    public void showhead(){
        if(isempty()){
            System.out.println("队列中没有数据!");
        }else{
            System.out.println("队列的头数据为:" + arry[front % maxsize]);
        }
    }
}

7、总结

1>提示“Duplicated code fragment”时,代表:在同一个项目里,于不同的文件中存在有相同的代码块

2>使用Scanner in = new Scanner(System.in)后,可以调用in.close()方法,调用后,在接下来的代码中无法再使用Scanner,即使再声明一次也无法使用Scanner

 在上述示例中,运行结果为:程序已退出!

所以为什么要去调用in.close()方法?

如果创建了Scanner对象,却不关闭,那么在方法结束后,Scanner对象并不会立刻进入被回收的队列中,这就使得计算机有一定的负担。如果确定之后不会再使用Scanner,那么也可以提前终止。

3>直接输出Java中的类,得到的结果:自动调用getClass().getName() + '@'  + Integer.toHexString(hashCode()),也就是每个Java类自带的toString()方法。@后面的表示十六进制的哈希值。
4>快速生成对象快捷键:Ctrl+Alt+v

5>自得人生哲理之一:不去主动伤害别人,但是当被伤害时,不要给自己担上气氛调节的责任,该发脾气就发,考虑别人时,别人不一定去考虑你。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值