当前位置:   article > 正文

数据结构之队列的实现(附源码)_队列的实现代码

队列的实现代码

目录

一、队列的概念及结构

二、队列的实现

 拓展:循环队列

三、初学的队列以及栈和队列结合的练习题


一、队列的概念及结构

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头

二、队列的实现

队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。

 具体代码如下(C语言实现):

  1. #pragma once
  2. //Queue.h
  3. // 链式结构:表示队列
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <assert.h>
  7. typedef int QDateType;
  8. typedef struct QListNode
  9. {
  10. struct QListNode* _next;
  11. QDateType _data;
  12. }QNode;
  13. // 队列的结构
  14. typedef struct Queue
  15. {
  16. QNode* _front;//队头
  17. QNode* _rear;//队尾
  18. int size;
  19. }Queue;
  20. // 初始化队列
  21. void QueueInit(Queue* q);
  22. // 队尾入队列
  23. void QueuePush(Queue* q, QDateType data);
  24. // 队头出队列
  25. void QueuePop(Queue* q);
  26. // 获取队列头部元素
  27. QDateType QueueFront(Queue* q);
  28. // 获取队列队尾元素
  29. QDateType QueueBack(Queue* q);
  30. // 获取队列中有效元素个数
  31. int QueueSize(Queue* q);
  32. // 检测队列是否为空,如果为空返回非零结果,如果非空返回0
  33. int QueueEmpty(Queue* q);
  34. // 销毁队列
  35. void QueueDestroy(Queue* q);
  1. //Queue.c
  2. #include "Queue.h"
  3. void QueueInit(Queue* q)
  4. {
  5. assert(q);
  6. q->_front = NULL;
  7. q->_rear = NULL;
  8. q->size = 0;
  9. }
  10. void QueuePush(Queue* q, QDateType data)
  11. {
  12. assert(q);
  13. QNode* tmp = (QNode*)malloc(sizeof(QNode));
  14. if (tmp == NULL)
  15. {
  16. perror("tmp malloc");
  17. exit(-1);
  18. }
  19. tmp->_data = data;
  20. tmp->_next = NULL;
  21. if (q->_rear == NULL)
  22. {
  23. q->_front = q->_rear = tmp;
  24. }
  25. else
  26. {
  27. q->_rear->_next = tmp;
  28. q->_rear = tmp;
  29. }
  30. q->size++;
  31. }
  32. void QueuePop(Queue* q)
  33. {
  34. assert(q);
  35. assert(QueueEmpty(q));
  36. if (q->_front->_next == NULL)
  37. {
  38. free(q->_front);
  39. q->_front = q->_rear = NULL;
  40. }
  41. else
  42. {
  43. QNode* next = q->_front->_next;
  44. free(q->_front);
  45. q->_front = next;
  46. }
  47. q->size--;
  48. }
  49. QDateType QueueFront(Queue* q)
  50. {
  51. assert(q);
  52. assert(QueueEmpty(q));
  53. return q->_front->_data;
  54. }
  55. QDateType QueueBack(Queue* q)
  56. {
  57. assert(q);
  58. assert(QueueEmpty(q));
  59. return q->_rear->_data;
  60. }
  61. int QueueSize(Queue* q)
  62. {
  63. assert(q);
  64. return q->size;
  65. }
  66. int QueueEmpty(Queue* q)
  67. {
  68. assert(q);
  69. return q->size;
  70. }
  71. void QueueDestroy(Queue* q)
  72. {
  73. assert(q);
  74. QNode* cur = q->_front;
  75. while (cur)
  76. {
  77. Queue* next = cur->_next;
  78. free(cur);
  79. cur = next;
  80. }
  81. q->_front = q->_rear = NULL;
  82. q->size = 0;
  83. }
  1. //test.c
  2. #include "Queue.h"
  3. void test02()
  4. {
  5. Queue q1;
  6. QueueInit(&q1);
  7. QueuePush(&q1, 1);
  8. QueuePush(&q1, 2);
  9. QueuePush(&q1, 3);
  10. QueuePush(&q1, 4);
  11. QueuePush(&q1, 5);
  12. QueuePop(&q1);
  13. while (QueueEmpty(&q1))
  14. {
  15. printf("%d ", QueueFront(&q1));
  16. QueuePop(&q1);
  17. }
  18. printf("\n");
  19. QueueDestroy(&q1);
  20. }
  21. int main()
  22. {
  23. test02();
  24. return 0;
  25. }

 拓展:循环队列

如上图所示:循环队列的节点数一般会比要求的节点数多一个,以便区分空的循环队列和满的循环队列。空的循环队列front和rear指向同一个节点,满的循环队列可以理解为rear = front + 1。

三、初学的队列以及栈和队列结合的练习题

题目一:设计循环队列

  • MyCircularQueue(k): 构造器,设置队列长度为 k 。
  • Front: 从队首获取元素。如果队列为空,返回 -1 。
  • Rear: 获取队尾元素。如果队列为空,返回 -1 。
  • enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
  • deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
  • isEmpty(): 检查循环队列是否为空。
  • isFull(): 检查循环队列是否已满。
  1. typedef struct
  2. {
  3. int* a;
  4. int front;
  5. int rear;
  6. int k;
  7. } MyCircularQueue;
  8. MyCircularQueue* myCircularQueueCreate(int k)
  9. {
  10. MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
  11. obj->a = (int*)malloc(sizeof(int)*(k+1));
  12. obj->front = obj->rear = 0;
  13. obj->k = k;
  14. return obj;
  15. }
  16. bool myCircularQueueIsEmpty(MyCircularQueue* obj)
  17. {
  18. //front和rear相等即为空
  19. return obj->front == obj->rear;
  20. }
  21. bool myCircularQueueIsFull(MyCircularQueue* obj)
  22. {
  23. //数学方法判满
  24. return (obj->rear + 1) % (obj->k + 1) == obj->front;
  25. }
  26. bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)
  27. {
  28. if(myCircularQueueIsFull(obj))
  29. return false;
  30. obj->a[obj->rear] = value;
  31. ++obj->rear;
  32. //不然rear可能越界
  33. obj->rear %= (obj->k+1);
  34. return true;
  35. }
  36. bool myCircularQueueDeQueue(MyCircularQueue* obj)
  37. {
  38. if(myCircularQueueIsEmpty(obj))
  39. return false;
  40. obj->front++;
  41. obj->front %= (obj->k+1);
  42. return true;
  43. }
  44. int myCircularQueueFront(MyCircularQueue* obj)
  45. {
  46. if(myCircularQueueIsEmpty(obj))
  47. return -1;
  48. else
  49. return obj->a[obj->front];
  50. }
  51. int myCircularQueueRear(MyCircularQueue* obj)
  52. {
  53. if(myCircularQueueIsEmpty(obj))
  54. return -1;
  55. else
  56. //数学方法
  57. return obj->a[(obj->rear + obj->k) % (obj->k + 1)];
  58. }
  59. void myCircularQueueFree(MyCircularQueue* obj)
  60. {
  61. free(obj->a);
  62. free(obj);
  63. }

题目二:用队列实现栈

思路:用两个队列,保持一个队列为空一个不为空,当要出栈的时候就将不为空的队列中除了队尾的元素全都入到为空的队列中,然后将唯一的那个元素出栈。

  1. typedef int QDateType;
  2. typedef struct QListNode
  3. {
  4. struct QListNode* _next;
  5. QDateType _data;
  6. }QNode;
  7. // 队列的结构
  8. typedef struct Queue
  9. {
  10. QNode* _front;
  11. QNode* _rear;
  12. int size;
  13. }Queue;
  14. void QueueInit(Queue* q)
  15. {
  16. assert(q);
  17. q->_front = NULL;
  18. q->_rear = NULL;
  19. q->size = 0;
  20. }
  21. void QueuePush(Queue* q, QDateType data)
  22. {
  23. assert(q);
  24. QNode* tmp = (QNode*)malloc(sizeof(QNode));
  25. if (tmp == NULL)
  26. {
  27. perror("tmp malloc");
  28. exit(-1);
  29. }
  30. tmp->_data = data;
  31. tmp->_next = NULL;
  32. if (q->_rear == NULL)
  33. {
  34. q->_front = q->_rear = tmp;
  35. }
  36. else
  37. {
  38. q->_rear->_next = tmp;
  39. q->_rear = tmp;
  40. }
  41. q->size++;
  42. }
  43. void QueuePop(Queue* q)
  44. {
  45. assert(q);
  46. assert(QueueEmpty(q));
  47. if (q->_front->_next == NULL)
  48. {
  49. free(q->_front);
  50. q->_front = q->_rear = NULL;
  51. }
  52. else
  53. {
  54. QNode* next = q->_front->_next;
  55. free(q->_front);
  56. q->_front = next;
  57. }
  58. q->size--;
  59. }
  60. QDateType QueueFront(Queue* q)
  61. {
  62. assert(q);
  63. assert(QueueEmpty(q));
  64. return q->_front->_data;
  65. }
  66. QDateType QueueBack(Queue* q)
  67. {
  68. assert(q);
  69. assert(QueueEmpty(q));
  70. return q->_rear->_data;
  71. }
  72. int QueueSize(Queue* q)
  73. {
  74. assert(q);
  75. return q->size;
  76. }
  77. int QueueEmpty(Queue* q)
  78. {
  79. assert(q);
  80. return q->size;
  81. }
  82. void QueueDestroy(Queue* q)
  83. {
  84. assert(q);
  85. QNode* cur = q->_front;
  86. while (cur)
  87. {
  88. Queue* next = cur->_next;
  89. free(cur);
  90. cur = next;
  91. }
  92. q->_front = q->_rear = NULL;
  93. q->size = 0;
  94. }
  95. typedef struct
  96. {
  97. Queue q1;
  98. Queue q2;
  99. } MyStack;
  100. MyStack* myStackCreate()
  101. {
  102. MyStack* tmp = (MyStack*)malloc(sizeof(MyStack));
  103. QueueInit(&tmp->q1);
  104. QueueInit(&tmp->q2);
  105. return tmp;
  106. }
  107. void myStackPush(MyStack* obj, int x)
  108. {
  109. if(QueueEmpty(&obj->q1))
  110. {
  111. QueuePush(&obj->q1, x);
  112. }
  113. else
  114. {
  115. QueuePush(&obj->q2, x);
  116. }
  117. }
  118. int myStackPop(MyStack* obj)
  119. {
  120. Queue* empty = &obj->q1;
  121. Queue* noempty = &obj->q2;
  122. if(QueueEmpty(&obj->q1))
  123. {
  124. empty = &obj->q2;
  125. noempty = &obj->q1;
  126. }
  127. while(QueueSize(noempty) > 1)
  128. {
  129. QueuePush(empty, QueueFront(noempty));
  130. QueuePop(noempty);
  131. }
  132. int top = QueueFront(noempty);
  133. QueuePop(noempty);
  134. return top;
  135. }
  136. int myStackTop(MyStack* obj)
  137. {
  138. if(QueueEmpty(&obj->q1))
  139. return QueueBack(&obj->q1);
  140. else
  141. return QueueBack(&obj->q2);
  142. }
  143. bool myStackEmpty(MyStack* obj)
  144. {
  145. int ret1, ret2;
  146. if(QueueEmpty(&obj->q1) == 0)
  147. ret1 = 0;
  148. else
  149. ret1 = 1;
  150. if(QueueEmpty(&obj->q2) == 0)
  151. ret2 = 0;
  152. else
  153. ret2 = 1;
  154. if(ret1 == 0 && ret2 == 0)
  155. return true;
  156. else
  157. return false;
  158. }
  159. void myStackFree(MyStack* obj)
  160. {
  161. QueueDestroy(&obj->q1);
  162. QueueDestroy(&obj->q2);
  163. free(obj);
  164. }

题目三:用栈实现队列

思路:使用两个栈,一个push栈一个pop栈,先往push栈中堆入元素,出队时,先将push栈中的元素先pop到pop栈中,再从pop栈中pop元素,其间再有元素堆入入到push栈中。

  1. typedef int STDataType;
  2. typedef struct Stack
  3. {
  4. STDataType* _a;
  5. int _top; // 栈顶
  6. int _capacity; // 容量
  7. }Stack;
  8. void StackInit(Stack* ps)
  9. {
  10. assert(ps);
  11. ps->_a = NULL;
  12. ps->_top = 0;
  13. ps->_capacity = 0;
  14. }
  15. void StackPush(Stack* ps, STDataType data)
  16. {
  17. assert(ps);
  18. if (ps->_capacity == ps->_top)
  19. {
  20. int newCapacity = ps->_capacity == 0 ? 4 : ps->_capacity * 2;
  21. STDataType* tmp = (STDataType*)realloc(ps->_a,sizeof(STDataType) * newCapacity);
  22. if (tmp == NULL)
  23. {
  24. perror("realloc fail");
  25. exit(-1);
  26. }
  27. ps->_a = tmp;
  28. ps->_capacity = newCapacity;
  29. }
  30. ps->_a[ps->_top] = data;
  31. ps->_top++;
  32. }
  33. void StackPop(Stack* ps)
  34. {
  35. assert(ps);
  36. assert(ps->_top > 0);
  37. ps->_top--;
  38. }
  39. STDataType StackTop(Stack* ps)
  40. {
  41. assert(ps);
  42. assert(ps->_top > 0);
  43. return ps->_a[ps->_top - 1];
  44. }
  45. int StackSize(Stack* ps)
  46. {
  47. assert(ps);
  48. return ps->_top;
  49. }
  50. int StackEmpty(Stack* ps)
  51. {
  52. return ps->_top;
  53. }
  54. void StackDestroy(Stack* ps)
  55. {
  56. assert(ps);
  57. free(ps->_a);
  58. ps->_a = NULL;
  59. ps->_capacity = 0;
  60. ps->_top = 0;
  61. }
  62. typedef struct
  63. {
  64. Stack pushst;
  65. Stack popst;
  66. } MyQueue;
  67. MyQueue* myQueueCreate()
  68. {
  69. MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));
  70. StackInit(&obj->pushst);
  71. StackInit(&obj->popst);
  72. return obj;
  73. }
  74. void myQueuePush(MyQueue* obj, int x)
  75. {
  76. StackPush(&obj->pushst, x);
  77. }
  78. int myQueuePeek(MyQueue* obj)
  79. {
  80. //pop栈为空就往其中堆入元素
  81. if(StackEmpty(&obj->popst) == 0)
  82. {
  83. while(StackEmpty(&obj->pushst) > 0)
  84. {
  85. StackPush(&obj->popst, StackTop(&obj->pushst));
  86. StackPop(&obj->pushst);
  87. }
  88. }
  89. return StackTop(&obj->popst);
  90. }
  91. int myQueuePop(MyQueue* obj)
  92. {
  93. int front = myQueuePeek(obj);
  94. StackPop(&obj->popst);
  95. return front;
  96. }
  97. bool myQueueEmpty(MyQueue* obj)
  98. {
  99. int ret1, ret2;
  100. if(StackEmpty(&obj->pushst) == 0)
  101. ret1 = 0;
  102. else
  103. ret1 = 1;
  104. if(StackEmpty(&obj->popst) == 0)
  105. ret2 = 0;
  106. else
  107. ret2 = 1;
  108. if(ret1 == 0 && ret2 == 0)
  109. return true;
  110. else
  111. return false;
  112. }
  113. void myQueueFree(MyQueue* obj)
  114. {
  115. StackDestroy(&obj->pushst);
  116. StackDestroy(&obj->popst);
  117. free(obj);
  118. }

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

闽ICP备14008679号