当前位置:   article > 正文

用数组和链表来模拟队列结构_c++ 用链表模拟队列和用数组模拟队列

c++ 用链表模拟队列和用数组模拟队列

1.队列

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

       2. 队列存储数据的原则是:先进先出。

     

  2. 数组模拟队列的思路

      1. 队列本身就是一个有序的列表,如果要使用数组的结构来储存队列的数据。就要有以下声明:

             maxSize 表示队列的最大容量。  

       2.  队列的输出输入分别从队列的前后端处理,定义队列的前端下标为front ,队列的下标为rear。

            front会随着队列的输出而改变,rear会随队列的输入改变。 

      3. 当数据存入队列时,成为“add",add的处理步骤如下:

                 第一:当队列为空时,即front=rear, 将尾指针向后移动:rear+1。

                第二:如果尾指针rear小于队列的最大下标maxSize-1,将数据存入到到rear所值的元素数组中,当rear=maxSize-1,

                            队列满了,无法存入数据。

3. 代码实现

 

  1. public class ArryQueue {
  2. //使用数组模拟队列
  3. private int maxSize;//表示队列的最大容量
  4. private int front;//队列的头
  5. private int rear;//队列的尾
  6. private int[] arr;//该数组用来存放数据,模拟队列
  7. //创建队列的构造器
  8. public ArryQueue(int arrMaxSize){
  9. maxSize=arrMaxSize;
  10. arr=new int[maxSize];
  11. front=-1;//指向队列头部,-1是指向头部的前一个位置,看图
  12. rear=-1;//指定队列尾,指向队列的尾的数据(就是队列的最后一个数据)
  13. }
  14. //判断队列是否满了
  15. public boolean isFull(){
  16. return rear==maxSize-1;
  17. }
  18. //判断队列是否为空
  19. public boolean isEmpty(){
  20. return rear==front;
  21. }
  22. //将数据插入到队列中
  23. public void addQueue(int n){
  24. if(isFull()){
  25. System.out.println("队列满了,不能加入数据");
  26. return;
  27. }
  28. rear++;//让rear向后移动
  29. arr[rear]=n;
  30. }
  31. //获取队列中的数据
  32. public int getQueue(){
  33. if(isEmpty()){
  34. //通过抛出异常
  35. throw new RuntimeException("队列为空,不能取出数据");
  36. }
  37. front++;//让front后移
  38. return arr[front];
  39. }
  40. //显示队列中的所有元素
  41. public void showQueu(){
  42. //遍历
  43. if(isEmpty()){
  44. System.out.println("队列空的,没有数据");
  45. return;
  46. }
  47. for (int i = 0; i < arr.length; i++) {
  48. System.out.printf("arr[%d]=%d\n",i,arr[i]);
  49. }
  50. }
  51. //显示队列的头数据,不是去除数据
  52. public int headQueu(){
  53. //判断
  54. if(isEmpty()){
  55. throw new RuntimeException("队列为空,不能取出数据");
  56. }
  57. return arr[front+1];
  58. }
  59. //测试
  60. public static void main(String[] args) {
  61. //创建一个队列
  62. ArryQueue queue=new ArryQueue(3);
  63. char key=' ';//接受用户的输入
  64. Scanner scanner=new Scanner(System.in);
  65. boolean loop=true;
  66. //输出一个菜单
  67. while(loop){
  68. System.out.println("s(show):显示队列");
  69. System.out.println("e(exit):退出队列");
  70. System.out.println("a(add):添加数据到队列");
  71. System.out.println("g(get):从队列中去除数据");
  72. System.out.println("h(head):查看队列头的数据");
  73. key=scanner.next().charAt(0);//接受一个字符
  74. switch (key){
  75. case 's':
  76. queue.showQueu();
  77. break;
  78. case 'a':
  79. System.out.println("输入一个数");
  80. int value=scanner.nextInt();
  81. queue.addQueue(value);
  82. break;
  83. case 'g':
  84. try {
  85. int queue1 = queue.getQueue();
  86. System.out.printf("取出的数据为%d\n",queue1);
  87. }catch (Exception e){
  88. System.out.println(e.getMessage());
  89. }
  90. break;
  91. case 'h':
  92. try {
  93. int queue2 = queue.headQueu();
  94. System.out.printf("队列的头元素的数据为%d\n",queue2);
  95. }catch (Exception e){
  96. System.out.println(e.getMessage());
  97. }
  98. break;
  99. case 'e':
  100. //退出
  101. scanner.close();
  102. loop=false;
  103. break;
  104. default:
  105. break;
  106. }
  107. }
  108. System.out.println("程序退出");
  109. }
  110. }

  4. 问题分析:

         现在的队列只能使用一次,就不能在重复使用,达不到复用的效果。

        我们可以通过使用算法优化,改进成一个环形队列。

 

5. 数组模拟环形队列

      对上述代码进行优化,充分使用数组,因此可以将数组看成环形的。

 

6. 分析:

             1.  调整front的含义,front指向队列的第一个元素,arr [front] =第一个元素。此时front的初始值为0。

             2. 调整real的含义,rear指向队列的最后一个元素的后一个位置(倒数第二个元素),因为我们想留出一个空间作为约                      定。 rear的初始值为0.

             3. 队列满的条件:  (rear+1)%maxSize= front 。

             4. 队列空的条件:  rear == front 。

             5. 队列有效数据的个数    (real + maxSize - front )% maxSize

7 代码实现

  1. public class CirleQueueDemo {
  2. //使用数组模拟环形队列
  3. private int maxSize;//表示队列的最大容量
  4. private int front;//队列的头,指向队列的头
  5. private int rear;//队列的尾,指向队列的最后一个元素的后一个位置,希望留出一个空间作为约定
  6. private int[] arr;//该数组用来存放数据,模拟环形队列
  7. //创建队列的构造器
  8. public CirleQueueDemo(int arrMaxSize){
  9. maxSize=arrMaxSize;
  10. arr=new int[maxSize];
  11. //front=0;//指向队列头部,
  12. //rear=0;//指定队列尾,
  13. }
  14. //判断队列是否满了
  15. public boolean isFull(){
  16. return (rear+1)%maxSize==front;
  17. }
  18. //判断队列是否为空
  19. public boolean isEmpty(){
  20. return rear==front;
  21. }
  22. //将数据插入到队列中
  23. public void addQueue(int n){
  24. if(isFull()){
  25. System.out.println("队列满了,不能加入数据");
  26. return;
  27. }
  28. arr[rear]=n;
  29. //将rear后移,这里必须考虑取模
  30. rear=(rear+1)%maxSize;
  31. }
  32. //获取队列中的数据
  33. public int getQueue(){
  34. if(isEmpty()){
  35. //通过抛出异常
  36. throw new RuntimeException("队列为空,不能取出数据");
  37. }
  38. //1.先把元素取出来,存储到临时变量中
  39. int v=arr[front];
  40. //2 front后移,这时需要考虑取模
  41. front=(front+1)%maxSize;
  42. //3 将保存的变量返回
  43. return v;
  44. }
  45. //显示队列中的所有元素
  46. public void showQueu(){
  47. //遍历
  48. if(isEmpty()){
  49. System.out.println("队列空的,没有数据");
  50. return;
  51. }
  52. for (int i=front; i < front+size(); i++) {
  53. System.out.printf("arr[%d]=%d\n",i%maxSize,arr[i%maxSize]);
  54. }
  55. }
  56. //得到当前队列中的有效数据的个数
  57. public int size(){
  58. return (rear+maxSize-front)%maxSize;
  59. }
  60. //显示队列的头数据,不是去除数据
  61. public int headQueu(){
  62. //判断
  63. if(isEmpty()){
  64. throw new RuntimeException("队列为空,不能取出数据");
  65. }
  66. return arr[front];
  67. }
  68. //测试
  69. public static void main(String[] args) {
  70. //创建一个队列
  71. CirleQueueDemo queue=new CirleQueueDemo(4);//设置为4,队列中的有效数据最大为3,留出了一个约定孔空间
  72. char key=' ';//接受用户的输入
  73. Scanner scanner=new Scanner(System.in);
  74. boolean loop=true;
  75. //输出一个菜单
  76. while(loop){
  77. System.out.println("s(show):显示队列");
  78. System.out.println("e(exit):退出队列");
  79. System.out.println("a(add):添加数据到队列");
  80. System.out.println("g(get):从队列中去除数据");
  81. System.out.println("h(head):查看队列头的数据");
  82. key=scanner.next().charAt(0);//接受一个字符
  83. switch (key){
  84. case 's':
  85. queue.showQueu();
  86. break;
  87. case 'a':
  88. System.out.println("输入一个数");
  89. int value=scanner.nextInt();
  90. queue.addQueue(value);
  91. break;
  92. case 'g':
  93. try {
  94. int queue1 = queue.getQueue();
  95. System.out.printf("取出的数据为%d\n",queue1);
  96. }catch (Exception e){
  97. System.out.println(e.getMessage());
  98. }
  99. break;
  100. case 'h':
  101. try {
  102. int queue2 = queue.headQueu();
  103. System.out.printf("队列的头元素的数据为%d\n",queue2);
  104. }catch (Exception e){
  105. System.out.println(e.getMessage());
  106. }
  107. break;
  108. case 'e':
  109. //退出
  110. scanner.close();
  111. loop=false;
  112. break;
  113. default:
  114. break;
  115. }
  116. }
  117. System.out.println("程序退出");
  118. }

           

数组模拟队列2:

  

  1. package Queue.VirtulQueue;
  2. import java.util.ArrayList;
  3. public class ArrayQueuedemo {
  4. public static void main(String[] args) {
  5. ArrayQueue arrayQueue=new ArrayQueue<Integer>();
  6. arrayQueue.inQueue(1);
  7. arrayQueue.inQueue(2);
  8. arrayQueue.inQueue(3);
  9. arrayQueue.inQueue(4);
  10. arrayQueue.inQueue(5);
  11. System.out.println("队中的元素个数"+arrayQueue.size());
  12. System.out.println("队中的首元素"+arrayQueue.firstQueue());
  13. System.out.println("队中的尾元素"+arrayQueue.lastQueue());
  14. arrayQueue.outQueue();
  15. arrayQueue.outQueue();
  16. System.out.println("队中的元素个数"+arrayQueue.size());
  17. System.out.println("队中的首元素"+arrayQueue.firstQueue());
  18. System.out.println("队中的尾元素"+arrayQueue.lastQueue());
  19. }
  20. }
  21. class ArrayQueue<T>{
  22. private ArrayList<T> array=new ArrayList<T>();//成员变量 array 来存储元素怒
  23. private int front;//成员变量,指向队列的首位置
  24. private int real;//成员变量,指向队列尾元素的下一个位置。
  25. public ArrayQueue() {
  26. front=0;
  27. real=0;
  28. }
  29. //判断队列是否为空
  30. Boolean Empty(){
  31. return front==real;
  32. }
  33. //入队
  34. void inQueue(T item){
  35. array.add(item);
  36. real++;
  37. }
  38. //查看队列的大小
  39. int size(){
  40. return real-front;
  41. }
  42. //查看队列的首元素
  43. T firstQueue(){
  44. if (Empty()){
  45. return null;
  46. }
  47. return array.get(front);
  48. }
  49. //查看队列的尾元素
  50. T lastQueue(){
  51. if (Empty()){
  52. return null;
  53. }
  54. return array.get(real-1);
  55. }
  56. //出队
  57. void outQueue(){
  58. if (real>front){
  59. front++;
  60. }else {
  61. System.out.println("队列为空");
  62. }
  63. }
  64. }

链表模拟队列

  1. package Queue.VirtulQueue;
  2. public class ListQueue {
  3. public static void main(String[] args) {
  4. Queue<Integer> queue=new Queue<Integer>();
  5. queue.inQueue(1);
  6. queue.inQueue(2);
  7. queue.inQueue(3);
  8. queue.inQueue(4);
  9. queue.inQueue(5);
  10. System.out.println("队列的大小"+queue.size());
  11. System.out.println("队列的首元素"+queue.fqueue());
  12. System.out.println("队列的尾元素"+queue.lqueue());
  13. queue.outQueue();
  14. System.out.println("队列的大小"+queue.size());
  15. System.out.println("队列的首元素"+queue.fqueue());
  16. System.out.println("队列的尾元素"+queue.lqueue());
  17. }
  18. }
  19. class Queue<T>{
  20. private LNode<T> head;//定义链表的头结点,指向队列的头
  21. private LNode<T> end;//定义链表的尾结点,指向队列的尾
  22. //构造函数,一开始初始化队列为空
  23. public Queue() {
  24. head=end=null;
  25. }
  26. //队列是否为空
  27. Boolean Empty(){
  28. return head==null;
  29. }
  30. //入队
  31. void inQueue(T item){
  32. LNode<T> tmp=new LNode<>();
  33. tmp.data=item;
  34. tmp.next=null;
  35. if (head==null){
  36. head=end=tmp;
  37. }else {
  38. end.next=tmp;
  39. end=tmp;
  40. }
  41. }
  42. //队列元素的个数
  43. int size(){
  44. int i=0;
  45. LNode<T> tmp=head;
  46. while (tmp!=null){
  47. tmp=tmp.next;
  48. i++;
  49. }
  50. return i;
  51. }
  52. //出队
  53. void outQueue(){
  54. if (Empty()){
  55. System.out.println("队列为空");
  56. }
  57. head=head.next;
  58. if (head==null){
  59. end=null;
  60. }
  61. }
  62. //队列的首元素
  63. T fqueue(){
  64. if (Empty()){
  65. System.out.println("队列为空");
  66. return null;
  67. }
  68. return head.data;
  69. }
  70. //队列的尾
  71. T lqueue(){
  72. if (end==null){
  73. System.out.println("队列为空");
  74. return null;
  75. }
  76. return end.data;
  77. }
  78. }
  79. class LNode<T>{
  80. T data;
  81. LNode<T> next;
  82. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/306636
推荐阅读
相关标签
  

闽ICP备14008679号