java 环形队列 遍历_Java数据结构和算法(八)队列中数组模拟环形队列的实现(附Java代码)...

本篇文章主要是为了解决上一篇文章中,数组使用一次就不能继续使用的问题,由于上一篇文章中的数组没有达到复用的效果,因此本篇文章使用算法,将数组改造成一个环形队列,以此达到复用的效果。

首先进行数组模拟环形队列的思路分析:

(1)将front变量的含义做一个调整,front指向队列中的第一个元素,也就是说arr[front]就是队列的第一个元素,front的初始值为0。

(2)将rear变量的含义做一个调整,rear指向队列的最后一个元素的后一个位置,因为希望空出一个空间作为约定,rear的初始值为0。

(3)当队列满时,条件是(rear+1)%maxSize ==front

(4)当队列为空时,条件是 rear == front

(5)这样分析后,队列中有效的数据个数为(rear+maxSize-front)%maxSize。假设front=0,rear=2  公式算完之后为2

(6)可以在原来的队列基础上修改得到一个环形队列

环形队列主要算法上的改动就是使用了取模  %来实现循环复用。

下面就是修改后的部分关键方法代码:

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

首先构造器中,front和rear的初始值发生改变,从-1变为0

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

判断队列是否满的条件发生改变

//添加数据到队列    public void addQueue(int n){        if(isFull()){            System.out.println("队列满,不能加入数据");            return;        }        //直接将数据加入        arr[rear] = n;        //将rear后移,考虑取模        rear = (rear+1) % maxSize;   //直接加1会导致数组越界    }

addQueue方法发生改变,直接将数据加入后需要取模,而不是+1,一直+1会导致数组越界。

//获取队列的数据,出队列    public int getQueue(){        if(isEmpty()){            System.out.println("队列空,不能取出数据");            //通过抛出异常            throw new RuntimeException("队列空,不能取出数据");        }        //这里需要分析出front是指向队列的第一个元素        //1.先把front对应的值保存到一个临时变量        //2.将front后移,考虑取模        //3.将临时保存的变量返回        int value = arr[front];        front = (front +1) % maxSize;        return value;    }

getQueue方法发生改变,需要先把front对应的值保存到一个临时变量,之后将front后移,考虑取模,最后将临时保存的变量返回。

//显示队列的所有数据    public void showQueue(){        if(isEmpty()){            System.out.println("队列为空,没有数据");            return;        }        //思路:从front开始遍历,遍历多少个元素        //        for(int i=front;i

showQueue方法中,用到了思路中提到的,队列中有效数据的个数,因此写了一个size方法,代码如下:

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

最后运行截图如下,主要区别就是,之前的数组队列,在队列已经满之后,进行取出数据的操作,然后不能再添加,而现在的环形队列,假设队列中为10,20,30,队列已满,之后取出队列头部数据10,现在队列为20,30,可以继续进行添加操作,例如添加数据40,这样队列为20,30,40。

c1fa057b0cc3edcc156b2884eb63c8ac.png

程序正确按照上面例子中的算法运行,结果正确。

最后附上数组模拟环形队列的全部代码:

/** To change this license header, choose License Headers in Project Properties.* To change this template file, choose Tools | Templates* and open the template in the editor.*/package queue;import java.util.Scanner;/**** @author Administrator*/public class CircleArrayQueueDemo {public static void main(String[] args){//测试数组模拟环形队列System.out.println("测试数组模拟环形队列");//这里设置的4,其队列的有效数据最大是3CircleArray queue =  new CircleArray(4);char key = ' ';//接收用户输入Scanner input = 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(hrad):查看队列头的数据");key = input.next().charAt(0);switch(key){case 's':queue.showQueue();break;case 'a':System.out.println("输入一个数");int value = input.nextInt();queue.addQueue(value);break;case 'g':try{int res =queue.getQueue();System.out.println("取出的数据是"+ res);} catch(Exception e){System.out.println(e.getMessage());}break;case 'h': //查看队列头的数据try{int res =queue.headQueue();System.out.println("取出的队列头数据是"+ res);} catch(Exception e){System.out.println(e.getMessage());}break;case 'e':input.close();loop = false;break;default:break;}}System.out.println("程序退出");}}class CircleArray{private int maxSize; //表示数组的最大容量private int front ; //front指向队列头部元素,初始值为0private int rear; //rear指向队列的最后一个元素的后一个位置private 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;   //直接加1会导致数组越界}//获取队列的数据,出队列public int getQueue(){if(isEmpty()){System.out.println("队列空,不能取出数据");//通过抛出异常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.print(arr[i%maxSize]+"\t");}}//求出当前队列有效数据的个数public int size(){return (rear + maxSize - front) % maxSize;}//显示队列的头数据,注意不是取出数据public int headQueue(){if(isEmpty()){System.out.println("队列为空,没有数据");throw new RuntimeException("队列空,不能取出数据");}return arr[front ];}}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值