数据结构 顺序结构循环队列的基本操作(java实现) 代码解析

为什么使用循环队列?

因为队列是一种先进先出的存储结构,并且元素只可以在队尾插入,在队头删除。在这种多次的插入、删除操作后,就会出现一种“假溢出”现象。“假溢出”现象的意思就是在队列前面还有空余位置的时候,最后面已经到达了队尾,无法再插入新的元素了。

代码解析

首先是循环队列基本操作的代码(代码是教材是教材上的,只有一些细微的改变)

public class sequenceQueue<T> {
    final int MaxSize=10;
    private T queueArray[];
    private int front,rear;

1 最开始是定义了一个名为sequenceQueue的类,其中 T 为泛类型。
2 设定了这个循环队列的初始长度(最大长度)MaxSize。
3 存储元素的队列数组对象。
4 队列的头指针和尾指针。

【队列的初始化】

	 public sequenceQueue(){     
        front=rear=0;
        queueArray=(T[])new Object[MaxSize];
    }

1 无参初始化
2 在之前有两个指针,头指针和尾指针,在初始时让头指针和尾指针都在“0”号位
3 由于不能实例化一个泛型对象,所以在构造时可以先实例化一个新的最大长度为MaxSize的Object数组。

【入队】

    public void EnQueue(T obj){
        if((rear+1)%queueArray.length==front){
            T[] p=(T[])new Object[queueArray.length*2];

1 因为循环队列是一个圈圈型的,所以如果尾指针+1和头指针在一个位置,就说明这个循环队列已经满了。
2 在前面判断完循环队列是否已经满了。如果满了,就要申请新的空间(原空间的2倍)。

		if(rear==((T[])queueArray).length-1){
			for(int i=1;i<=rear;i++)
                    p[i]=queueArray[i];
            }

在判断循环队列已经满了,申请了新的空间,就需要把原来空间中已存在的元素移到新的空间中,但在转移元素时,元素在原来的空间中是有两种排列情况的,上面这段代码就是其中的一种情况——头指针在尾指针前面,这个说法有点抽象,看我画的图图叭!
在这里插入图片描述
啊啊啊!对了!在图里可以看出0号位上没有任何元素,这是循环队列的一个特点!为了可以有效地区分队空和队满的情况,如果把front指针所指的位置空出来,这样就可以通过rear== front来确定队空,通过(rear+1) % queueArray.length==front;来判断队满。
那么问题又来了! (rear+1) % queueArray.length == front;这个是啥?就又回到了一个很基本的问题,循环队列是怎么实现的。循环队列最本质思想就是取余数,%就是其余的意思。

继续解释代码
1 判断rear的位置是否在最后面(就是循环队列中0号位前面的那个)
2-3 如果是,直接用for循环语句从1号位的元素,移到最后面rear指针指的元素。注意!在移动到新表时要从1号位开始放哦!

            else{
            int i,j=1;
            for(i=front=1;i<queueArray.length;i++,j++)
                p[j]=queueArray[i];
            for(i=0;i<=rear;i++,j++)
                p[j]=queueArray[i];
            front=0;
            rear=queueArray.length-1;
        }

从else就能看出来这是另一种情况了!就是尾指针不在最后一个位置的时候,还是看图吧!
在这里插入图片描述
这种情况在移动的时候就有点麻烦了!不仅仅要移动过去,还要把这个顺序掰正了!
解释代码
1 首先要把新表的0号位让出来,原因和前面说的一样,为了区分满和空要牺牲一个空间。
2-5 就是把元素复制过去的代码,其中2-3是先复制头指针后面的一位(因为front指针指的位置为空)到最后一个位置的元素(图中就是BCDE元素),4-5行为复制0号位到尾指针所指的元素(图中为F)
6-7 再给头指针和尾指针指到新表的对应位置~

        queueArray=p;
        }
         rear=(rear+1)%queueArray.length;
         queueArray[rear]=obj;
    }

1 给新表一个新的名字,申请的时候他叫p,元素都挪完了,名字也给他吧!
2-3 终于!!入队啦!先把尾指针指到下一个位置,再把元素放进去。

【出队】

      public T DeQueue(){
        if(isEmpty()){
            System.out.println("队列已空,无法出队!");
			return null;
}
    	front=(front+1)%queueArray.length;
    	return queueArray[front];
}

出队就没那么多乱七八糟的麻烦了!只需要判断队列是否为空就好~
代码解释
1-3 体现了一种容错能力,就是在出队时首先要判断队伍的情况,队伍里啥都没有就直接打印"队列已空,无法出队!"
4-5 队列是先进先出的结构,因此在出队时需要先把头指针后移,然后把其中的元素移除。

【取头元素】

    public T GetTop(){
		if(isEmpty()){
    		System.out.println("队列已空,无法读取元素!");
			return null;
		}
     	front=(front+1)%queueArray.length;
    	 return queueArray[front];
	}

1-3 和出队差不多,既然要取头元素,那就要先判断队列是否为空
4-5 取头元素,返回头指针后一个位置的元素,还有另一种写法,可以给这两句话写成一句,如下。

	return queueArray[(front+1)%queueArray.length];

【判断队列是否为空】

	public boolean isEmpty(){
		return front==rear;
	}

1-2 如果front和rear相等,就返回true,反之返回false。

【求队列长度】

	public int size(){
		return (rear-front+queueArray.length)%queueArray.length;
	}

就像前面的第一张图,rear指针在5,front指针在0,图中的队列长度为6。
计算过程:(5-0+6)%6=5,就是五个元素吖!
第二张图,rear指针在0,front指针在1,图中队列长度为6.
计算过程:(0-1+6)%6=5,一共五个元素!

【遍历队列】

	public void nextOrder(){
		int i,j=front;
		for(i=1;i<=size();i++){
			j=(j+1)%queueArray.length;
  			System.out.println(queueArray[j]);
		}
	}

1 申请两个变量,i和j,其中j在front指针的位置。
2-4 for循环i是防止重复遍历,j是用来取元素输出元素。

【清空队列】

	public void clear(){
		front=rear=0;
	}
}

头指针尾指针直接回到解放前,全部打回到0号位。

接下来是主类的代码部分(教材上只给了上面方法的代码,下面的主类代码,我也忘了当时是网上找的还是编的了,但是我会尽力解释的!!!)

public class Text5 {
    public static void main(String[] args) {
        sequenceQueue<Integer> sequenceQueue = new sequenceQueue<Integer>();
        sequenceQueue.EnQueue(23);
        sequenceQueue.EnQueue(56);
        sequenceQueue.EnQueue(12);
        sequenceQueue.EnQueue(49);
        sequenceQueue.EnQueue(35);

1 申请新的int类型的数组
2-6 入队入队入队

        Integer s = sequenceQueue.size();
        System.out.println(sequenceQueue.GetTop());

1 定义一个int型变量s,存放队列长度
2 输出头指针

        for (Integer integer = 0;integer<s;integer++){
            System.out.println(sequenceQueue.DeQueue());
        }

1-2 全部出队!

        System.out.println(sequenceQueue.isEmpty());

判空,输出结果为true或false

        sequenceQueue.EnQueue(35);
        s=sequenceQueue.size();

1 入队
2 求队列长度

        for(Integer integer = 0;integer<s;integer++){
            System.out.println(sequenceQueue.DeQueue());
        }
        System.out.println(sequenceQueue.isEmpty());
    }
}

1-2 又删???
3 又判空???

xswl当时我咋没注意到,这么可爱的操作…

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值