当前位置:   article > 正文

队列及其基本操作_队列的基本操作

队列的基本操作

一.队列

1.队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。

队列是一种先进先出(First In First ut)的表简FIF。的一端称为队尾,允许删除的一端称为队头。假设队列是 q= ( a1,a2·....,a),那么a1 就是队头元素,而 an 是队尾元素。这样我们就可以删除时,总是从 ai 开始,而插入时,列在最后。这也比较符合我们通常生活中的习惯,排在第一个的优先出列,最后来的当然排在队伍最后, 如图所示:

 

队列存储结构的实现有以下两种方式:
顺序队列:在顺序表的基础上实现的队列结构。
链队列:在链表的基础上实现的队列结构。

两者的区别仅是顺序表和链表的区别,即在实际的物理空间中,数据集中存储的队列是顺序队列,分散存储的队列是链队列。

 2.队列如何设计

队列只有链式的设计方法,其本身分为多种队列,如顺序队列和循环队列,还有衍生的优先队列等等,以顺序队列的设计为例。

首先是队列的结点设计,可以设计出两个结构体,一个结构体 Node 表示结点,其中包含有 data 域和 next 指针,如图:

 其中 data 表示数据,其可以是简单的类型,也可以是复杂的结构体。next 指针表示,下一个的指针,其指向下一个结点,通过 next 指针将各个结点链接。

添加一个结构体,其包括了两个分别永远指向队列的队尾和队首的指针。 

 

 3.队列的抽象数据类型:

InitQueue:初始化操作,建立一个空队列 Q。
DestroyQueue:若队列Q存在,则销毁它。
ClearQueue :将队列Q清空。
QueueEmpty:若队列Q为空,返回true,否则返回 false。
GetHead:若队列Q存在且非空,用e返回队列Q的队头元素。
EnQueue:若队列Q存在,插入新元素e 到队列Q中并成为队尾元素。
DeQueue:删除队列Q中队头元素,并用e返回其值。
QueueLength:返回队列Q的元素个数。

  1. #define OK 1
  2. #define ERROR 0
  3. #define OVERFLOW -1
  4. //#define MAXQSIZE 100 //最大队列长度
  5. typedef int Status;
  6. const int MaxQSize = 100;
  7. typedef int ElemType;
  8. typedef struct
  9. {
  10. ElemType* base; //初始化的动态分配存储空间
  11. int front; //头指针,若队列不空,指向队列头元素
  12. int rear; //尾指针,若队列不空,指向队列尾元素的下一个位置
  13. int cursize; //循环队列元素的个数, 为0时队列空,当cursize == MAXQSIZE 时队列满
  14. int maxsize;
  15. }SeqQueue;
  16. //构造一个空队列
  17. Status InitQueue(SeqQueue* pe)
  18. {
  19. assert(pe != nullptr);
  20. pe->base = (ElemType*)malloc(sizeof(ElemType) * MaxQSize);
  21. if (nullptr == pe->base)
  22. {
  23. exit(EXIT_FAILURE);
  24. }
  25. pe->cursize = 0;
  26. pe->front = 0;
  27. pe->rear = 0;
  28. pe->maxsize = MaxQSize;
  29. return OK;
  30. }
  31. //销毁队列,不再存在
  32. void DestroyQueue(SeqQueue* pe)
  33. {
  34. assert(pe != nullptr);
  35. free(pe->base);
  36. pe->base = nullptr;
  37. pe->front = pe->rear = pe->cursize = pe->maxsize = 0;
  38. }
  39. //将队列清为空
  40. void ClearQueue(SeqQueue* pe)
  41. {
  42. assert(pe != nullptr);
  43. pe->cursize = 0;
  44. pe->front = 0;
  45. pe->rear = 0;
  46. }
  47. //返回队列的元素个数,即为队列的长度
  48. int QueueLength(const SeqQueue* pe)
  49. {
  50. assert(pe != nullptr);
  51. return pe->cursize;
  52. }
  53. //检查循环队列是否为空
  54. bool IsEmpty(const SeqQueue* pe) {
  55. assert(pe != nullptr);
  56. return pe->cursize == 0;
  57. }
  58. // 检查循环队列是否已满。
  59. bool IsFull(const SeqQueue* pe) {
  60. assert(pe != nullptr);
  61. return pe->cursize == pe->maxsize;
  62. }
  63. //若队列不空,则用pval返回队头元素,并返回OK;否则返回ERROR
  64. Status GetHead(const SeqQueue* pe, ElemType* pval)
  65. {
  66. assert(pe != nullptr && pval != nullptr);
  67. if (IsEmpty(pe))
  68. {
  69. return ERROR;
  70. }
  71. *pval = pe->base[pe->front];
  72. return OK;
  73. }
  74. //若队列不空,则用pval返回的队尾元素,并返回OK;否则返回ERROR
  75. Status GetTail(const SeqQueue* pe, ElemType* pval)
  76. {
  77. assert(pe != nullptr && pval != nullptr);
  78. if (IsEmpty(pe))
  79. {
  80. return ERROR;
  81. }
  82. int rindex = pe->rear - 1;
  83. if (rindex < 0) rindex = pe->maxsize - 1;
  84. }
  85. //队尾插入元素val, val为新的队尾元素
  86. Status EnQueue(SeqQueue* pe, ElemType val)
  87. {
  88. assert(pe != nullptr);
  89. if (IsFull(pe))
  90. {
  91. return ERROR;
  92. }
  93. pe->base[pe->rear] = val;
  94. pe->rear = (pe->rear + 1) % pe->maxsize;
  95. pe->cursize += 1;
  96. return OK;
  97. }
  98. //若队列不空,则删除队头元素,用pval返回其值,并返回0K,否则返回ERROR
  99. Status DeQueue(SeqQueue* pe, ElemType* pval)
  100. {
  101. assert(pe != nullptr && pval != nullptr);
  102. if (IsEmpty(pe))
  103. {
  104. return ERROR;
  105. }
  106. *pval = pe->base[pe->front];
  107. pe->front = (pe->front + 1) % pe->maxsize;
  108. return OK;
  109. }
  110. int main()
  111. {
  112. SeqQueue seq;
  113. InitQueue(&seq);
  114. DestroyQueue(&seq);
  115. return 0;
  116. }

二.链队列

用链表表示的队列简称为链队列。一个链队列显然需要两个分别指示队头和队尾的指针(分别称为头指针和尾指针)才能惟一确定。这里,和线性表的单链表一样,为了操作方便起见,我们也给链队列添加一个头结点,并令头指针指向头结点。 由此,空的链队列的判决条件为头指针和尾指针均指向头结点。 

 链队列的基本操作及其代码展示:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <assert.h>
  4. #define OK 0
  5. #define ERROR -1
  6. typedef int Status;
  7. typedef int QElemType;
  8. typedef struct QNode
  9. {
  10. QElemType data;
  11. struct QNode* next;
  12. }QNode, * QueuePtr;
  13. typedef struct
  14. {
  15. QueuePtr front; // 对头指针
  16. QueuePtr rear; // 队尾指针
  17. int cursize; // 元素个数
  18. }LinkQueue;
  19. QNode* Buynode(QElemType val, QNode* narg = nullptr) //购买节点 数据域 next域
  20. {
  21. QNode* s = (QNode*)malloc(sizeof(QNode)); //购买QNode结点
  22. if (nullptr == s) //malloc不一定成功
  23. {
  24. exit(EXIT_FAILURE); // _exit; abort(); exit终止当前的进程
  25. }
  26. s->data = val;
  27. s->next = narg;
  28. return s;
  29. }
  30. void Freenode(QNode* p)
  31. {
  32. assert(p != nullptr);
  33. free(p); //释放结点
  34. }
  35. //构造一个空队列
  36. Status InitQueue(LinkQueue* pe)
  37. {
  38. assert(pe != nullptr);
  39. pe->cursize = 0;
  40. pe->front = pe->rear = Buynode(0);
  41. return OK;
  42. }
  43. //将队列清为空
  44. void ClearQueue(LinkQueue* pe)
  45. {
  46. assert(pe != nullptr);
  47. while (pe->front->next != nullptr)
  48. {
  49. QNode* q = pe->front->next;
  50. pe->front->next = q->next;
  51. Freenode(q);
  52. }
  53. }
  54. //销毁队列,不再存在
  55. void DestroyQueue(LinkQueue* pe)
  56. {
  57. assert(pe != nullptr);
  58. ClearQueue(pe);
  59. Freenode(pe->front);
  60. pe->front = pe->rear = nullptr;
  61. }
  62. //返回队列的元素个数,即为队列的长度
  63. int QueueLength(const LinkQueue* pe)
  64. {
  65. assert(pe != nullptr);
  66. return pe->cursize;
  67. }
  68. //检查队列是否为空
  69. bool IsEmpty(const LinkQueue* pe)
  70. {
  71. assert(pe != nullptr);
  72. return pe->cursize == 0;
  73. }
  74. //若队列不空,则用pval返回队头元素,并返回OK;否则返回ERROR
  75. Status GetHead(const LinkQueue* pe, QElemType* pval)
  76. {
  77. assert(pe != nullptr);
  78. if (IsEmpty(pe))
  79. {
  80. return ERROR;
  81. }
  82. *pval = pe->front->next -> data;
  83. return OK;
  84. }
  85. //若队列不空,则删除队头元素,用pval返回其值,并返回0K,否则返回ERROR
  86. Status DeQueue(LinkQueue* pe, QElemType* pval)
  87. {
  88. assert(pe != nullptr && pval != nullptr);
  89. if (IsEmpty(pe))
  90. {
  91. return ERROR;
  92. }
  93. QNode* q = pe->front->next; // first;
  94. *pval = q->data;
  95. pe->front->next = q->next;
  96. Freenode(q);
  97. pe->cursize -= 1;
  98. if (pe->cursize == 0)
  99. {
  100. pe->rear = pe->front;
  101. }
  102. return OK;
  103. }
  104. int main()
  105. {
  106. LinkQueue myq;
  107. InitQueue(&myq);
  108. int x;
  109. while (!IsEmpty(&myq))
  110. {
  111. DeQueue(&myq, &x);
  112. printf("%d\n", x);
  113. }
  114. DestroyQueue(&myq);
  115. return 0;
  116. }

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

闽ICP备14008679号