队列是一个有序列表,可以用数组或者链表来实现,遵循先入先出的原则,即先存入队列的数据,要先取出.后存入的要后取出.

 Java编程内功-数据结构与算法「队列」(java常用数据结构与算法) JAVA 数据结构 算法 第1张

基本介绍

队列是一个有序列表,可以用数组或者链表来实现

遵循先入先出的原则,即先存入队列的数据,要先取出.后存入的要后取出

数组模拟队列

队列本身是有序列表,若使用数组的结构来存储队列的数据,则队列数组的声明如下图,其中maxSize是该队列的最大容量.

因为队列的输入\输出是分别从前后端来处理,因此需要两个变量front及rear分别记录队列前后端的下标,front会随着数据输出而改变,而rear则是随着数据输入而改变.

 Java编程内功-数据结构与算法「队列」(java常用数据结构与算法) JAVA 数据结构 算法 第2张

代码案例

  1. packagecom.structures.queue;
  2. importjava.util.Scanner;
  3. publicclassArrayQueueDemo{
  4. publicstaticvoidmain(String[]args){
  5. ArrayQueuearrayQueue=newArrayQueue(3);
  6. charkey='';//接受用户输入
  7. Scannerscanner=newScanner(System.in);
  8. booleanloop=true;
  9. //输出一个菜单
  10. while(loop){
  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. key=scanner.next().charAt(0);
  17. switch(key){
  18. case's':
  19. arrayQueue.showQueue();
  20. break;
  21. case'a':
  22. System.out.println("输入一个整数");
  23. intvalue=scanner.nextInt();
  24. arrayQueue.addQueue(value);
  25. break;
  26. case'g':
  27. try{
  28. intqueue=arrayQueue.getQueue();
  29. System.out.printf("取出的数据是%d",queue);
  30. }catch(Exceptione){
  31. System.out.println(e.getMessage());
  32. }
  33. break;
  34. case'e':
  35. scanner.close();
  36. loop=false;
  37. break;
  38. case'h':
  39. try{
  40. inthead=arrayQueue.headQueue();
  41. System.out.printf("取出队列头的数据是%d",head);
  42. }catch(Exceptione){
  43. System.out.println(e.getMessage());
  44. }
  45. default:
  46. break;
  47. }
  48. }
  49. System.out.println("程序退出");
  50. }
  51. }
  52. //使用数组模拟队列-编写一个ArrayQueue类
  53. classArrayQueue{
  54. //表示数组最大容量
  55. privateintmaxSize;
  56. //队列头
  57. privateintfront;
  58. //队列尾
  59. privateintrear;
  60. //用于存放数据,模拟队列
  61. privateint[]arr;
  62. //创建队列构造器
  63. publicArrayQueue(intarrMaxSize){
  64. maxSize=arrMaxSize;
  65. arr=newint[maxSize];
  66. front=-1;//指向队列头的前一个位置
  67. rear=-1;//指向队列尾的数据,即就是队列最后一个数据
  68. }
  69. //判断队列是否满
  70. publicbooleanisFull(){
  71. returnrear==maxSize-1;
  72. }
  73. //判断队列是否为空
  74. publicbooleanisEmpty(){
  75. returnrear==front;
  76. }
  77. //添加数据到队列
  78. publicvoidaddQueue(intn){
  79. if(isFull()){
  80. System.out.println("队列不能加入数据");
  81. return;
  82. }
  83. rear++;//让rear后移
  84. arr[rear]=n;
  85. }
  86. //获取队列数据,出队列
  87. publicintgetQueue(){
  88. if(isEmpty()){
  89. thrownewRuntimeException("队列为空,不能取数据");
  90. }
  91. front++;
  92. returnarr[front];
  93. }
  94. //显示队列所有数据
  95. publicvoidshowQueue(){
  96. if(isEmpty()){
  97. System.out.println("队列为空,没有数据");
  98. }
  99. for(inti=0;i<this.arr.length;i++){
  100. System.out.printf("arr[%d]=%d\n",i,arr[i]);
  101. }
  102. }
  103. //显示队列的头数据,注意不是取数据
  104. publicintheadQueue(){
  105. if(isEmpty()){
  106. thrownewRuntimeException("队列为空,没有数据");
  107. }
  108. returnarr[front+1];
  109. }
  110. }

问题分析

  1. 目前这个数组使用一次就不能用,没有达到复用的效果.
  2. 将这个数组使用算法,改进成一个环形的队列:取模%

改进成环形队列的思路分析

  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.

环形队列代码案例

  1. packagecom.structures.queue;
  2. importjava.util.Scanner;
  3. publicclassCircleArrayQueue{
  4. publicstaticvoidmain(String[]args){
  5. CircleArrayarrayQueue=newCircleArray(4);//这里设置4,其队列的有效数据最大是3
  6. charkey='';//接受用户输入
  7. Scannerscanner=newScanner(System.in);
  8. booleanloop=true;
  9. //输出一个菜单
  10. while(loop){
  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. key=scanner.next().charAt(0);
  17. switch(key){
  18. case's':
  19. arrayQueue.showQueue();
  20. break;
  21. case'a':
  22. System.out.println("输入一个整数");
  23. intvalue=scanner.nextInt();
  24. arrayQueue.addQueue(value);
  25. break;
  26. case'g':
  27. try{
  28. intqueue=arrayQueue.getQueue();
  29. System.out.printf("取出的数据是%d",queue);
  30. }catch(Exceptione){
  31. System.out.println(e.getMessage());
  32. }
  33. break;
  34. case'e':
  35. scanner.close();
  36. loop=false;
  37. break;
  38. case'h':
  39. try{
  40. inthead=arrayQueue.headQueue();
  41. System.out.printf("取出队列头的数据是%d",head);
  42. }catch(Exceptione){
  43. System.out.println(e.getMessage());
  44. }
  45. default:
  46. break;
  47. }
  48. }
  49. System.out.println("程序退出");
  50. }
  51. }
  52. classCircleArray{
  53. //表示数组最大容量
  54. privateintmaxSize;
  55. //front变量的含义做一个调整:front就指向队列的第一个元素,也就是arr[front]就是队列的第一个元素,front的初始值=0
  56. privateintfront;
  57. //rear变量的含义做一个调整:rear指向队列的最后一个元素的后一个位置,因为希望空出一个空间作为约定.rear初始值=0
  58. privateintrear;
  59. //用于存放数据,模拟队列
  60. privateint[]arr;
  61. publicCircleArray(intarrMaxSize){
  62. maxSize=arrMaxSize;
  63. arr=newint[maxSize];
  64. }
  65. //判断队列是否满
  66. publicbooleanisFull(){
  67. return(rear+1)%maxSize==front;
  68. }
  69. //判断队列是否为空
  70. publicbooleanisEmpty(){
  71. returnrear==front;
  72. }
  73. //添加数据到队列
  74. publicvoidaddQueue(intn){
  75. if(isFull()){
  76. System.out.println("队列满,队列不能加入数据");
  77. return;
  78. }
  79. //直接将数据加入
  80. arr[rear]=n;
  81. //将rear后移,这里必须考虑取模
  82. rear=(rear+1)%maxSize;
  83. }
  84. //获取队列数据,出队列
  85. publicintgetQueue(){
  86. if(isEmpty()){
  87. thrownewRuntimeException("队列为空,不能取数据");
  88. }
  89. //这里需要分析front是指向队列的第一个元素,
  90. //1.先把front对应的值保存到一个临时变量,
  91. //2.将front后移,考虑取模
  92. //3.将临时保存的变量返回
  93. intvalue=arr[front];
  94. front=(front+1)%maxSize;
  95. returnvalue;
  96. }
  97. //显示队列所有数据
  98. publicvoidshowQueue(){
  99. if(isEmpty()){
  100. System.out.println("队列为空,没有数据");
  101. }
  102. //从front开始遍历
  103. for(inti=front;i<front+size();i++){
  104. System.out.printf("arr[%d]=%d\n",i%maxSize,arr[i%maxSize]);
  105. }
  106. }
  107. //求出当前队列有效数据的个数
  108. publicintsize(){
  109. return(rear+maxSize-front)%maxSize;
  110. }
  111. //显示队列的头数据,注意不是取数据
  112. publicintheadQueue(){
  113. if(isEmpty()){
  114. thrownewRuntimeException("队列为空,没有数据");
  115. }
  116. returnarr[front];
  117. }
  118. }

【编辑推荐】

  1. 凉凉,老板叫我开发一个简单的工作流引擎...
  2. Windows10将迎来翻天覆地变化!今年第一个更新来了
  3. 2021年将迎来六大网络安全趋势
  4. Windows 10近年最大改进!Windows10 21H2新特性抢先看
  5. 小爱同学竟然推出了PC版?带你体验电脑版小爱

转载请说明出处
知优网 » Java编程内功-数据结构与算法「队列」(java常用数据结构与算法)

发表评论

您需要后才能发表评论