1 import java.util.Scanner; 2 //数组模拟队列 3 public class ArrayQueueDemo { 4 public static void main(String[] args) { 5 ArrayQueue arrayQueue = new ArrayQueue(3); 6 Scanner sc = new Scanner(System.in); 7 boolean loop = true; 8 while(loop) { 9 System.out.println("*******a、添加数据*************g、取数据******************"); 10 System.out.println("*******s、展示队列*************h、展示头部数据**************"); 11 System.out.println("*******************e、退出程序***************"); 12 System.out.println("请选择:"); 13 char command = sc.next().charAt(0); 14 switch(command) { 15 case 'a': 16 try { 17 System.out.println("请输入您要插入的数据"); 18 int n = sc.nextInt(); 19 arrayQueue.addQueue(n); 20 } catch (Exception e) { 21 System.out.println(e.getMessage()); 22 } 23 break; 24 case 'g': 25 try { 26 System.out.println("取出数据:" + arrayQueue.getQueue()); 27 } catch (Exception e) { 28 System.out.println(e.getMessage()); 29 } 30 break; 31 case 's': 32 arrayQueue.showQueue(); 33 break; 34 case 'h': 35 try { 36 System.out.println("头部数据为:" + arrayQueue.showHeadQueue()); 37 } catch (Exception e) { 38 System.out.println(e.getMessage()); 39 } 40 break; 41 case 'e': 42 sc.close(); 43 loop = false; 44 System.out.println("退出程序"); 45 break; 46 default: 47 System.out.println("不支持改选择"); 48 break; 49 } 50 } 51 } 52 } 53 54 class ArrayQueue{ 55 private int front; //队列头部【指向队列头部元素的上一个元素位置】 56 private int rear; //队列尾部 57 private int[] arr; 58 private int maxSize; //指定数组的大小 59 //构造器:初始化数据 60 public ArrayQueue(int maxSize) { 61 this.maxSize = maxSize; 62 arr = new int[maxSize]; 63 front = -1; 64 rear = -1; 65 } 66 67 //判断队列是否为空 68 public boolean isEmpty() { 69 return front == rear; 70 } 71 72 //判断队列是否满 73 public boolean isFull() { 74 return rear == maxSize - 1; 75 } 76 77 //向队列中添加元素 78 public void addQueue(int n) { 79 if(isFull()) { 80 System.out.println("队列满,不能添加数据"); 81 return; 82 } 83 //添加元素:即往尾部追加数据 84 arr[++rear] = n; 85 } 86 87 //向队列中取出元素 88 public int getQueue() { 89 if (isEmpty()) { 90 throw new RuntimeException("队列空,无数据"); 91 } 92 //取元素即取出索引位置为fron+1元素位置的数据 93 return arr[++front]; 94 } 95 96 //展示队列元素,即遍历数组 97 public void showQueue() { 98 if (isEmpty()) { 99 System.out.println("队列空,无数据"); 100 return; 101 } 102 for (int i = 0; i < arr.length; i++) { 103 System.out.printf("arr[%d] = %d\n", i, arr[i]); 104 } 105 } 106 107 //展示队列头部数据 108 public int showHeadQueue() { 109 if (isEmpty()) { 110 throw new RuntimeException("队列空,无数据"); 111 } 112 //即展示fron+1索引位置的值 113 return arr[front+1]; 114 } 115 }
上述过程实现了用数组模拟队列的过程,但是缺点也很明显:就是这个队列不能在有效的空间内复用数据,即每个地方存储的数据都是一次性的。
改进:实现用数组模拟环形队列:
1 import java.util.Scanner; 2 3 /** 4 * 调整: 5 * 1、front变量:arr[front]表示第一个元素,font初始值:0 6 * 2、rear变量:指向队列中最后一个元素的后一个位置,希望空出一个位置作为约定 7 * 3、当队列满时,(rear + 1) % maxSize == front 8 * 4、当队列为空时:front == rear 9 * 5、队列中有效数据的个数为:(rear + maxSize - front) % maxSize 10 * -->至此,可以得到一个环形队列 11 */ 12 public class CircleArrayQueueDemo { 13 14 public static void main(String[] args) { 15 System.out.println("测试数组模拟环形队列~~~"); 16 CircleArrayQueue arrayQueue = new CircleArrayQueue(4); 17 Scanner sc = new Scanner(System.in); 18 boolean loop = true; 19 while(loop) { 20 System.out.println("*******a、添加数据*************g、取数据******************"); 21 System.out.println("*******s、展示队列*************h、展示头部数据**************"); 22 System.out.println("*******************e、退出程序***************"); 23 System.out.println("请选择:"); 24 char command = sc.next().charAt(0); 25 switch(command) { 26 case 'a': 27 try { 28 System.out.println("请输入您要插入的数据"); 29 int n = sc.nextInt(); 30 arrayQueue.addQueue(n); 31 } catch (Exception e) { 32 System.out.println(e.getMessage()); 33 } 34 break; 35 case 'g': 36 try { 37 System.out.println("取出的数据为:" + arrayQueue.getQueue()); 38 } catch (Exception e) { 39 System.out.println(e.getMessage()); 40 } 41 break; 42 case 's': 43 try { 44 arrayQueue.showQueue(); 45 } catch (Exception e) { 46 System.out.println(e.getMessage()); 47 } 48 break; 49 case 'h': 50 try { 51 System.out.println("头部数据为:" + arrayQueue.showHeadQueue()); 52 } catch (Exception e) { 53 System.out.println(e.getMessage()); 54 } 55 break; 56 case 'e': 57 sc.close(); 58 loop = false; 59 System.out.println("退出程序"); 60 break; 61 default: 62 System.out.println("不支持改选择"); 63 break; 64 } 65 } 66 } 67 68 } 69 70 class CircleArrayQueue{ 71 private int front; //指向队列中的第一个元素的索引位置 72 private int rear; //指向队列中最后一个元素的索引位置的下一个位置 73 private int maxSize; //队列中最大的元素个数为maxSize - 1【空出一个位置作为约定】 74 private int[] arr; //数组,模拟实现队列 75 76 //创建构造器,用于初始化一些数据 77 public CircleArrayQueue(int maxSize) { 78 this.maxSize = maxSize; 79 arr = new int[maxSize]; 80 // front = 0; //默认值为0 81 // rear = 0; 82 } 83 84 //判断队列是否满了 85 public boolean isFull() { 86 return front == (rear + 1) % maxSize; 87 } 88 89 //判断队列是否为空 90 public boolean isEmpty() { 91 return front == rear; 92 } 93 94 //往队列中添加元素 95 public void addQueue(int n) { 96 if (isFull()) { 97 System.out.println("队列已满,不能添加数据~~~"); 98 return; 99 } 100 //添加数据,即往队列的尾部追加数据,追加完后rear指向的位置需要后移一位 101 //注:因为是环形队列,不能单纯地rear++,此处需要考虑到取模的情况 102 arr[rear] = n; 103 rear = (rear + 1) % maxSize; 104 } 105 106 //从队列中取出数据 107 public int getQueue() { 108 if (isEmpty()) { 109 throw new RuntimeException("队列为空,不能取出数据"); 110 } 111 //取出数据,即从头部front处取,取完后front指向的位置需要后移一位 112 //同添加数据一样,此处也需要考虑到取模的情况 113 /* 114 return arr[front]; 115 front = (front + 1) % maxSize; //这样写会导致front指针无法向后移动 116 */ 117 //需要定义一个临时变量用于保存当前arr[front]的值 118 int tmp = arr[front]; 119 front = (front + 1) % maxSize; //front指针向后移动一位 120 return tmp; 121 } 122 123 //遍历队列中的元素 124 public void showQueue() { 125 if (isEmpty()) { 126 throw new RuntimeException("队列空,无数据"); 127 } 128 for (int i = front; i < front + size(); i++) { 129 System.out.printf("arr[%d] = %d\n", i % maxSize,arr[i % maxSize]); 130 } 131 } 132 133 //返回当前队列中有效数字的个数 134 public int size() { 135 return (rear + maxSize - front) % maxSize; 136 } 137 138 //返回队列头部数据 139 public int showHeadQueue() { 140 if (isEmpty()) { 141 throw new RuntimeException("队列空,无头部数据"); 142 } 143 return arr[front]; 144 } 145 }
如此,便达到了存储空间复用的效果