队列
队列的含义:
1) 队列是一个有序的列表,可以用数组或是链表来实现
2) 遵循先入先出的原则.即:先存入队列的数据,先取出,后存入的要后取出.
数组模拟队列
如图:
![]()
|
解释:
①队列本身就是有序列表,若使用数组的结构来存储队列的数据,则队列声明如上图,最大容量是MaxSize.
②因为队列的输出和输入是分别从前后端来处理,因此需要两个变量分别来记录,front会随着数据的输出而改变,而rear则是随着数据的输入而改变
③相关的判断 首先添加一个数据rear+1 ,当front = rear 为空,当rear = maxSize-1时表示队列满了
代码呈现如下:
1 package DatabaseStructure.com.lsj.queue; 2 3 import java.util.Scanner; 4 5 /** 6 * Created by IDEA 7 * 创建人:wen 8 * 创建日期: 2019-08-12 9 * 创建时间: 10:29 10 * 数组模拟队列 11 * 存在问题:当我们将所有数据全部取出来之后,我们不能在去存入数据了,他会显示队列已满,产生这个问题的原因就是我们没有做成环形队列 12 */ 13 public class ArrayQueueDemo { 14 15 public static void main(String[] args) { 16 //测试 17 ArrayQueue queue = new ArrayQueue(3); 18 char key = ' ';//接收用户输入 19 Scanner scanner = new Scanner(System.in); 20 boolean loop = true; 21 while (loop){ 22 System.out.println("s(show):显示数据"); 23 System.out.println("e(exit):退出程序"); 24 System.out.println("a(add):添加数据到数列"); 25 System.out.println("g(get):从队列中取出数据"); 26 System.out.println("h(head):查看队列头的数据"); 27 key = scanner.next().charAt(0);//接收一个字符 28 switch (key){ 29 case 's': 30 queue.showQueue(); 31 break; 32 case 'a': 33 System.out.println("输入一个数"); 34 int val = scanner.nextInt(); 35 queue.addQueue(val); 36 break; 37 case 'e': 38 scanner.close(); 39 loop = false; 40 break; 41 case 'h': 42 try { 43 int i = queue.headQueue(); 44 System.out.printf("取出的队列头数据是%d\n",i); 45 }catch (Exception e){ 46 System.out.println(e.getMessage()); 47 } 48 break; 49 case 'g': 50 try { 51 int i = queue.getQueue(); 52 System.out.printf("取出的数据是%d\n",i); 53 }catch (Exception e){ 54 System.out.println(e.getMessage()); 55 } 56 break; 57 default: 58 System.out.println("输入有误!!!"); 59 break; 60 } 61 } 62 63 } 64 } 65 //使用数组模拟队列--编写一个ArrayQueue类 66 class ArrayQueue{ 67 private int maxSize;//表示数组的最大容量 68 private int front;//队列头 69 private int rear;//队列尾 70 private int[] arr; //该数组用于存放数据,模拟队列 71 72 //创建队列的构造器 73 public ArrayQueue(int maxSize){ 74 this.maxSize = maxSize; 75 arr = new int[maxSize]; 76 front = -1;//指向队列头部,分析出front是指向队列头的前一个位置 77 rear = -1;//指向队列尾,指向队列尾的数据 78 } 79 //判断队列是否满 80 public boolean isFull(){ 81 return rear == maxSize-1; 82 } 83 //判断队列是否为空 84 public boolean isEmpty(){ 85 return rear == front; 86 } 87 //添加数据到队列 88 public void addQueue(int n){ 89 //判断队列是否满 90 if (isFull()){ 91 System.out.println("队列满,不能加入数据~~"); 92 return; 93 } 94 arr[++rear] = n; 95 } 96 //获取队列数据,出队列 97 public int getQueue(){ 98 //判断队列是否为空 99 if (isEmpty()){ 100 throw new RuntimeException("队列为空"); 101 } 102 return arr[++front]; 103 } 104 //显示队列所有数据 105 public void showQueue(){ 106 //遍历 107 if (isEmpty()){ 108 System.out.println("队列为空!!"); 109 } 110 for (int i = 0; i < arr.length; i++) { 111 System.out.printf("arr[%d]=%d\n",i,arr[i]); 112 } 113 } 114 //显示队列的头数据,注意不是取出数据 115 public int headQueue(){ 116 //判断为空 117 if (isEmpty()){ 118 System.out.println("队列空没有数据"); 119 } 120 return arr[front+1]; 121 } 122 }
发现问题: 没有达到复用
解决方法: 使用环形的队列
数组实现环形队列(这里存在很多种方法,我主要取的相对比较好理解的方法)
实现思路:
①将front和rear指向链表的第一个节点(front = rear = 0)
②相关的条件:满的条件: (rear+1)%maxSize == front ,空的条件 : front == rear
③经过分析我们可以判断出链表中有限数据的个数 (rear+maxSize-front)%maxSize
代码实现
1 package DatabaseStructure.com.lsj.queue; 2 3 import java.util.Scanner; 4 5 /** 6 * Created by IDEA 7 * 创建人:wen 8 * 创建日期: 2019-08-12 9 * 创建时间: 14:42 10 */ 11 public class CircleArrayQueueDemo { 12 public static void main(String[] args) { 13 //测试 14 CircleQueue queue = new CircleQueue(3);//设置为3说明,他的有效空间是2 15 char key = ' ';//接收用户输入 16 Scanner scanner = new Scanner(System.in); 17 boolean loop = true; 18 while (loop) { 19 System.out.println("s(show):显示数据"); 20 System.out.println("e(exit):退出程序"); 21 System.out.println("a(add):添加数据到数列"); 22 System.out.println("g(get):从队列中取出数据"); 23 System.out.println("h(head):查看队列头的数据"); 24 key = scanner.next().charAt(0);//接收一个字符 25 switch (key) { 26 case 's': 27 queue.showQueue(); 28 break; 29 case 'a': 30 System.out.println("输入一个数"); 31 int val = scanner.nextInt(); 32 queue.addQueue(val); 33 break; 34 case 'e': 35 scanner.close(); 36 loop = false; 37 break; 38 case 'h': 39 try { 40 int i = queue.headQueue(); 41 System.out.printf("取出的队列头数据是%d\n", i); 42 } catch (Exception e) { 43 System.out.println(e.getMessage()); 44 } 45 break; 46 case 'g': 47 try { 48 int i = queue.getQueue(); 49 System.out.printf("取出的数据是%d\n", i); 50 } catch (Exception e) { 51 System.out.println(e.getMessage()); 52 } 53 break; 54 default: 55 System.out.println("输入有误!!!"); 56 break; 57 } 58 } 59 60 } 61 } 62 class CircleQueue { 63 private int maxSize;//表示数组的最大容量 64 private int front;//队列头 65 private int rear;//队列尾 66 private int[] arr; //该数组用于存放数据,模拟队列 67 68 //创建队列的构造器 69 public CircleQueue(int CimaxSize) { 70 maxSize = CimaxSize; 71 arr = new int[maxSize]; 72 front = 0;//指向队列头部, 73 rear = 0;//指向队列尾,指向队列尾的数据的后一个位置 74 } 75 76 //判断队列是否满 77 public boolean isFull() { 78 return (rear+1)%maxSize == front; 79 } 80 81 //判断队列是否为空 82 public boolean isEmpty() { 83 return rear == front; 84 } 85 86 //添加数据到队列 87 public void addQueue(int n) { 88 //判断队列是否满 89 if (isFull()) { 90 System.out.println("队列满,不能加入数据~~"); 91 return; 92 } 93 94 arr[rear] = n; 95 rear = (rear+1)%maxSize; 96 } 97 98 //获取队列数据,出队列 99 public int getQueue() { 100 //判断队列是否为空 101 if (isEmpty()) { 102 throw new RuntimeException("队列为空"); 103 } 104 //这里需要分析出,front是指向队列的第一个元素 105 //1.先把front对应的值保存到一个临时变量 106 //2.将front后移,考虑取模 107 //将临时保存变量返回 108 int i = arr[front]; 109 front = (front+1)%maxSize; 110 return i; 111 112 } 113 114 //显示队列所有数据 115 public void showQueue() { 116 //遍历 117 if (isEmpty()) { 118 System.out.println("队列为空!!"); 119 } 120 //思路:从front开始遍历,遍历多少个元素 121 for (int i = front; i < (front+size()); i++) { 122 System.out.printf("arr[%d]=%d\n", i%maxSize, arr[i%maxSize]); 123 } 124 } 125 //求出当前队列中有效数据的个数 126 public int size(){ 127 return (rear+maxSize-front)%maxSize; 128 } 129 130 131 //显示队列的头数据,注意不是取出数据 132 public int headQueue() { 133 //判断为空 134 if (isEmpty()) { 135 System.out.println("队列空没有数据"); 136 } 137 return arr[front]; 138 } 139 }
-----
注 : 链表实现队列,先实现完链表在实现