找回密码
 立即注册
首页 业界区 科技 数据结构之顺序队列

数据结构之顺序队列

晖顶蝇 17 小时前

数据结构之队列

什么是队列

  • 队列是和栈一样操作受限的线性表,栈是只允许在线性表的一端进行入栈和出栈操作,而队列是会允许在线性表的一端进行入队,在另外一端进行出队操作

队列的基本操作

  1. bool initQueue(Queue & Q); // 初始化队列
  2. void destroyQueue(Queue Q); // 如果是顺序队列则不需要销毁
  3. bool push(Queue & Q, ElemType x); // 入队
  4. bool pop(Queue & Q, ElemType & x); // 出队
  5. // 获取队头元素的值
  6. void getTop(Queue Q, ELemType & x);
  7. bool queueEmpty(Queue Q); // 判断队列是否为空
复制代码

顺序队列

  • 用静态数组实现的队列(使用顺序存储结构实现的队列)缺点:空间固定
    1.png

顺序队列的代码实现

  1. #include<stdio.h>
  2. #define Elemtype int
  3. #define MaxSize 10
  4. typedef struct SQueue{
  5. Elemtype data[MaxSize];
  6. size_t front,rear; // 队头和队尾指针(存储数组下标)
  7. }SQueue;
  8. bool initQueue(SQueue & Q)
  9. {
  10. Q.front = 0;
  11. Q.rear = 0;
  12. }
  13. // 入队
  14. bool push(Queue & Q, ElemType x)
  15. {
  16. // 如果队列满了则返回false
  17. if((Q.rear + 1) % MaxSize == Q.front)
  18. return false;
  19. Q.data[Q.rear] = x;
  20. Q.rear = (Q.rear+1) % MaxSize;
  21. }
  22. // 出队
  23. bool pop(Queue & Q, ElemType & x)
  24. {
  25. // 如果队列为空,则返回false
  26. if(Q.front == Q.rear)
  27. return false
  28. x = Q.data[Q.front];
  29. Q.front = (Q.front + 1) % MaxSize;
  30. }
  31. // 获取队头元素的值
  32. void getTop(Queue Q, ELemType & x){
  33. // 如果队列为空,则返回false
  34. if(Q.front == Q.rear)
  35. return false
  36. x = Q.data[Q.front];
  37. }
  38. // 判断队列是否为空
  39. bool SqueueEmpty(SQueue Q);{
  40. if(Q.front == Q.rear)
  41. return true;
  42. return false;
  43. }
复制代码

代码缺陷

上述代码实现的队列,会浪费一个存储空间,如何避免浪费一个存储空间呢?

  1. 使用一个length变量,存储队列的长度
  1. typedef struct SQueue{
  2. Elemtype data[MaxSize];
  3. size_t front,rear; // 队头和队尾指针(存储数组下标)
  4. Size_t length;
  5. }SQueue;
  6. bool initQueue(SQueue & Q)
  7. {
  8. Q.front = 0;
  9. Q.rear = 0;
  10. Q.length = 0; // 计数器
  11. }
  12. // 入队
  13. bool push(Queue & Q, ElemType x)
  14. {
  15. // 如果队列满了则返回false
  16. if(Q.front == Q.rear && Q.length == MaxSize)
  17. return false;
  18. Q.data[Q.rear] = x;
  19. Q.rear = (Q.rear+1) % MaxSize;
  20. Q.length++;
  21. }
  22. // 出队
  23. bool pop(Queue & Q, ElemType & x)
  24. {
  25. // 如果队列为空,则返回false
  26. if(Q.front == Q.rear && Q.length == 0)
  27. return false
  28. x = Q.data[Q.front];
  29. Q.front = (Q.front + 1) % MaxSize;
  30. Q.rear--;
  31. }
复制代码
  1. 使用一个flag变量,出队时将flag 置为0 , 入队将flag置为1
  1. typedef struct SQueue{
  2. Elemtype data[MaxSize];
  3. size_t front,rear; // 队头和队尾指针(存储数组下标)
  4. bool flag;
  5. }SQueue;
  6. bool initQueue(SQueue & Q)
  7. {
  8. Q.front = 0;
  9. Q.rear = 0;
  10. }
  11. // 入队
  12. bool push(Queue & Q, ElemType x)
  13. {
  14. // 如果队列满了则返回false
  15. if(Q.front == Q.rear && Q.flag = 1)
  16. return false;
  17. Q.data[Q.rear] = x;
  18. Q.rear = (Q.rear+1) % MaxSize;
  19. Q.flag = 1;
  20. }
  21. // 出队
  22. bool pop(Queue & Q, ElemType & x)
  23. {
  24. // 如果队列为空,则返回false
  25. if(Q.front == Q.rear && Q.flag == 0)
  26. return false
  27. x = Q.data[Q.front];
  28. Q.front = (Q.front + 1) % MaxSize;
  29. Q.rear--;
  30. Q.flat = 0;
  31. }
复制代码

链式队列

  • 用链表实现的队列(存储空间不固定,根据内存来确定)
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #define ElemType int
  4. typedef struct LinkNode { // 链式队列结点
  5. ElemType data;
  6. struct LinkNode* next;
  7. }LinkNode;
  8. typedef struct {
  9. LinkNode* front, * rear; // 队列的队头和队尾指针
  10. }LinkQueue;
  11. // 初始化链式队列
  12. bool initLinkQueue(LinkQueue& LQ)
  13. {
  14. LinkNode* n = (LinkNode*)malloc(sizeof(LinkNode));
  15. if (n == NULL)
  16. return false;
  17. n->next = NULL;
  18. LQ.front = n;
  19. LQ.rear = n;
  20. return true;
  21. }
  22. // 销毁链式队列
  23. void destoryQueue(LinkQueue& LQ)
  24. {
  25. LinkNode* cur = LQ.front->next;
  26. LinkNode* next;
  27. while (cur != NULL)
  28. {
  29. next = cur->next;
  30. free(cur);
  31. cur = next;
  32. }
  33. free(LQ.front); // 释放头结点
  34. LQ.front = NULL;
  35. LQ.rear = NULL;
  36. }
  37. // 判断链式队列为空
  38. bool isEmpty(LinkQueue LQ)
  39. {
  40. if (LQ.front == LQ.rear)
  41. return true;
  42. else
  43. return false;
  44. }
  45. // 入队
  46. bool push(LinkQueue& LQ, ElemType x)
  47. {
  48. LinkNode* n = (LinkNode*)malloc(sizeof(LinkNode));
  49. if (n == NULL)
  50. return false;
  51. n->data = x;
  52. n->next = NULL;
  53. LQ.rear->next = n;
  54. LQ.rear = n; // 修改队尾指针
  55. return true;
  56. }
  57. // 出队
  58. bool pop(LinkQueue& LQ, ElemType& x)
  59. {
  60. if (isEmpty(LQ)) // 判断链式队列是否为空
  61. return false;
  62. LinkNode* head = LQ.front;
  63. LinkNode* cur = head->next; // 当前要出的结点
  64. x = cur->data;
  65. head->next = cur->next;
  66. if (LQ.rear == cur) // 此次出队的是最后一个结点
  67. LQ.rear = LQ.front;
  68. free(cur); // 释放结点
  69. return true;
  70. }
  71. // 获取队头结点存放的数据
  72. bool getTop(LinkQueue& LQ, ElemType& x)
  73. {
  74. if (isEmpty(LQ)) // 判断链式队列是否为空
  75. return false;
  76. LinkNode* head = LQ.front;
  77. LinkNode* cur = head->next; // 队头结点
  78. x = cur->data;
  79. return true;
  80. }
  81. // 打印整个队列
  82. void printQueue(LinkQueue LQ)
  83. {
  84. LinkNode* cur = LQ.front->next; // 作为遍历整个队列的结点
  85. if(!isEmpty(LQ))
  86. {
  87. while (cur != NULL)
  88. {
  89. printf("%d <- ", cur->data);
  90. cur = cur->next;
  91. }
  92. printf("NULL\n");
  93. }
  94. }
  95. // 测试函数
  96. void test_LinkQueue(){
  97. LinkQueue LQ;
  98. initLinkQueue(LQ);
  99. push(LQ, 1);
  100. push(LQ, 2);
  101. push(LQ, 3);
  102. push(LQ, 4);
  103. printQueue(LQ);
  104. ElemType x = 0;
  105. pop(LQ, x);
  106. pop(LQ, x);
  107. printQueue(LQ);
  108. }
  109. int main()
  110. {
  111. test_LinkQueue();
  112. return 0;
  113. }
复制代码

队列的变种(双端队列)

双端队列:受限制的线性表,可以在线性表的两端进行插入和删除操作

  1. 双端队列只允许在队列的一端进行插入和删除操作就等价于栈
  2. 输入受限的双端队列: 只允许一端进行插入,两端允许删除的线性表
  3. 输出受限的双端队列: 只允许一段进行删除,两段允许插入的线性表

2.png

练习题:判断输出序列合法性

若数据元素输入序列为1,2,3,4,5 则哪些输出序列是合法的,哪些是非法的?


来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册