一、队列的介绍
队列是 有序 的,可以用 数组 或者 链表来实现,而且队列遵循一个 先入先出 的原则,即存入队列的数据,要先取出,后存入的要后取出。
二、用数组模拟队列思路
1、队列是有序的,若使用数组的结构来存储队列的数据,首先要用 maxsize 来指定队列的最大容量。
2、因为队列的输出、输入是分别从前后端来处理,因此需要两个变量 front 及 rear 分别记录队列前后端的下标,front 会随着数据输出而改变,而 rear 则是随着数据输入而改变,如果用C语言中的指针描述就是队首指针与队尾指针。
三、数组模拟队列图示
四、使用java语言描述队列
4.1 java代码如下:
1 public class ArrayQueueDemo { 2 3 public static void main(String[] args) { 4 //测试 5 ArrayQueue queue=new ArrayQueue(3); 6 char key=' ';//接收用户输入 7 Scanner scaner=new Scanner(System.in); 8 boolean loop=true; 9 while(loop){ 10 System.out.println("s(show):显示队列"); 11 System.out.println("e(exit):退出程序"); 12 System.out.println("a(add):添加数据到队列"); 13 System.out.println("g(get):从队列取出数据"); 14 System.out.println("h(head):查重队列头数据"); 15 key=scaner.next().charAt(0);//接收一个字符 16 switch(key){ 17 case 's': 18 queue.showQueue(); 19 break; 20 case 'a': 21 System.out.println("输入一个数"); 22 int value=scaner.nextInt(); 23 queue.addQueue(value); 24 break; 25 case 'g'://取出数据 26 try { 27 int res=queue.getQueue(); 28 System.out.printf("取出的数据是%d\n",res); 29 } catch (Exception e) { 30 // TODO: handle exception 31 System.out.println(e.getMessage()); 32 } 33 break; 34 case 'h'://查看队列头的数据 35 try { 36 int res=queue.headQueue(); 37 System.out.printf("队列头的数据是%d\n",res); 38 } catch (Exception e) { 39 // TODO: handle exception 40 System.out.println(e.getMessage()); 41 } 42 case 'e'://退出 43 scaner.close(); 44 loop=false; 45 break; 46 default: 47 break; 48 } 49 } 50 System.out.println("程序退出"); 51 } 52 53 } 54 //使用数组模拟队列-编写一个ArrayQueue类 55 class ArrayQueue{ 56 private int maxSize;//表示数组的最大容量 57 private int front;//队列头 58 private int rear;//队列尾 59 private int []arr;//该数组用于存放数据,模拟队列 60 61 //创建队列的构造器 62 public ArrayQueue(int arrMaxSize){ 63 maxSize=arrMaxSize; 64 arr=new int[maxSize]; 65 front=-1;//指向队列头部,分析出front是指向队列头部的前一个位置 66 rear=-1;//指向队列尾,指向队列尾的数据(即就是队列最后一个数据) 67 } 68 //判断队列是否满 69 public boolean isFull(){ 70 return rear==maxSize-1; 71 } 72 //判读队列是否为空 73 public boolean isEmpty(){ 74 return rear==front; 75 } 76 //添加数据到队列 77 public void addQueue(int n){ 78 //判断队列是否满 79 if(isFull()){ 80 System.out.println("队列满,不能加人数据"); 81 return; 82 } 83 rear++;//让rear后移 84 arr[rear]=n;// 85 } 86 //获取队列的数据,出队列 87 public int getQueue(){ 88 //判断队列是否空 89 if(isEmpty()){ 90 //通过抛出异常 91 throw new RuntimeException("队列为空,不能取数据"); 92 } 93 front++;//front后移 94 return arr[front]; 95 } 96 //显示所有的队列 97 public void showQueue(){ 98 //遍历 99 if(isEmpty()){ 100 System.out.println("队列空的,没有数据"); 101 return; 102 } 103 for (int i=0;i<arr.length;i++){ 104 System.out.printf("arr[%d]=%d\n",i,arr[i]); 105 } 106 } 107 //显示队列的头数据,注意不是取数据 108 public int headQueue(){ 109 if(isEmpty()){ 110 throw new RuntimeException("队列为空,不能取数据"); 111 } 112 return arr[front+1]; 113 114 } 115 }
4.2 问题分析并优化
1、目前数组使用一次就不能用,没有达到服用的效果
2、将这个数组使用算法,改进成一个环形的队列,取模:%
五、环形队列的介绍
可以将队列空间想象成一个 环形空间 ,这能使队列空间重复使用:无论插入还是删除,front(队头) 增1或 rear(队尾) 加1时超出所分配的空间,就让它指向这片连续空间的起始地址。取元素时先从队列头开始,取完后,下一个元素就成了队列头,依次循环。只有一个元素时,既是队列头,也是队列尾。
六、环形队列图示
七、用数组模拟环形队列思路
八、编写java代码实现环形队列
8.1 java代码如下:
1 public class CircleArrayQueueDemo { 2 //测试CircleArrayQueue 3 public static void main(String[] args) { 4 CircleArrayQueue arrayQueue = new CircleArrayQueue(4); 5 char key = ' '; //用于接收用户输入的命令 6 Scanner scanner = new Scanner(System.in); 7 boolean loop = true; 8 //输入一个菜单 9 while (loop) { 10 System.out.println("===========CircleArrayQueue============"); 11 System.out.println("s --> show : 显示队列"); 12 System.out.println("e --> exit : 退出系统"); 13 System.out.println("a --> add : 添加数据到队列"); 14 System.out.println("g --> get : 从队列中取出数据"); 15 System.out.println("h --> head : 查看队列头数据"); 16 System.out.println("===========CircleArrayQueue============"); 17 key = scanner.next().charAt(0); //接收用户输入命令 18 switch (key) { 19 case 's': //显示队列 20 try { 21 arrayQueue.showQueue(); 22 } catch (Exception e) { 23 e.printStackTrace(); 24 } 25 break; 26 case 'e': //退出系统 27 scanner.close(); 28 loop = false; 29 break; 30 case 'a': //向队列添加数据 31 try { 32 System.out.println("请输入要添加的数据"); 33 int num = scanner.nextInt(); 34 arrayQueue.addQueue(num); 35 } catch (Exception e) { 36 e.printStackTrace(); 37 } 38 break; 39 case 'g': //获取队列中的数据 40 try { 41 int res = arrayQueue.getQueue(); 42 System.out.printf("取出的数据是\t%d \n", res); 43 } catch (Exception e) { 44 e.printStackTrace(); 45 } 46 break; 47 case 'h': //查看队列的头数据 48 try { 49 int head = arrayQueue.headQueue(); 50 System.out.printf("队列的头数据是\t%d\n",head); 51 } catch (Exception e) { 52 e.printStackTrace(); 53 } 54 break; 55 default: 56 break; 57 } 58 } 59 System.out.println("队列退出!"); 60 } 61 } 62 63 64 class CircleArrayQueue { 65 private int maxSize; //表示数组的最大容量 66 private int front; //front做调整,指向队列中的第一个元素,默认初始值为0 67 private int rear; //rear做调整,约定指向最后一个元素的后一个位置,默认初始值为0 68 private int[] arr; //该数组用于存放数据,模拟队列 69 70 //创建队列的构造器 71 public CircleArrayQueue(int maxSize) { 72 this.maxSize = maxSize; 73 arr = new int[this.maxSize]; //创建对应长度的队列 74 //front & rear 默认给定的值为 0 ,所以可以省略赋值操作 75 } 76 77 //判断队列是否为满 78 public boolean isFull() { 79 return (rear + 1) % maxSize == front; 80 } 81 82 //判断队列是否为空 83 public boolean isEmpty() { 84 return front == rear; 85 } 86 87 //添加数据到队列 88 public void addQueue(int num) { 89 //判断队列是否为满 90 if (isFull()) { 91 System.out.println("队列已满不能添加有效数据!"); 92 return; 93 } 94 //rear初始值为0,直接指向的就是下一个位置。所以可以直接将数据加入 95 arr[rear] = num; 96 //因为要做成环形队列,所以 rear 取模向后 ++ 97 rear = (rear + 1) % maxSize; 98 } 99 100 //获取队列中的数据,出队列 101 public int getQueue() { 102 //判断队列是否为空 103 if (isEmpty()) { 104 //抛出异常 105 throw new RuntimeException("队列为空,无法获取有效数据 !"); 106 } 107 //这里不能直接将front返回,需要经过三步 108 /* 109 * 1. 先将front 对应的数据取出给临时变量 value 110 * 2. 将 front 后移 (取模后++) 111 * 3. 将临时变量存放的数据返回 112 */ 113 int value = arr[front]; 114 front = (front + 1) % maxSize; 115 return value; 116 } 117 118 //显示队列中的有效数据 119 public void showQueue() { 120 //判断队列是否为空 121 if (isEmpty()) { 122 throw new RuntimeException("队列为空,无法获取到有效数据! "); 123 } 124 //因为添加了环形操作,所以这里不能再fori循环遍历取值了 125 //思路: 从 front开始向后遍历多少个数据进行输出打印 126 for (int i = front; i < front + size(); i++) { 127 System.out.printf("arr[%d]=%d\n", i % maxSize, arr[i % maxSize]); 128 } 129 } 130 131 //获取队列中的有效数据个数 ==》 用于取代静态的arr.length 132 public int size() { 133 return (rear + maxSize - front) % maxSize; 134 } 135 136 //显示队列的头元素(只是显示,不是取出) 137 public int headQueue() { 138 //判断队列是否为空 139 if (isEmpty()) { 140 throw new RuntimeException("队列为空,无法获取头元素!"); 141 } 142 return arr[front]; 143 } 144 }
原文链接:https://blog.csdn.net/a1786742005/article/details/103977726