当前位置:   article > 正文

数据结构:队列(C语言描述)_队列取模是什么意思

队列取模是什么意思

目录

前言

根据存储结构划分队列的种类

循环队列结构体及宏定义如何定义

循环链表的初始化以及判断队空队满

数据入队、数据出队

获取队头数据、输出队列、清空队列

主函数测试


前言

主要内容:循环队列的初始化、队满队空的判断、数据出队、数据入队等操作,根据存储结构划分队列的种类。(如有错误,还望指正) 

队列也是线性表的一种,于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。队列中没有元素时,称为空队列。队列的数据元素又称为队列元素。在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出(FIFO—first in first out)线性表。生活中的队列我们可以看成排队(当然这里不包括插队)。

队列的种类和写法有很多种,本文主要讲解循环队列。其实各种种类的队列写法思路都是大同小异。

根据存储结构划分队列的种类

(1)顺序队列:使用数组作为存储结构,通过出队操作将数据弹出队列后,front之前的空间不能再次得到,浪费空间,会出现假溢出。

(2)循环队列:使用循环数组作为存储结构,将普通数组换成循环数组。在循环数组中,末尾元素的下一个元素不是数组外,而是数组的头元素。

(3)链式队列:单链表实现,动态分配内存避免假溢出的同时还可以延长队列。

(4)双端队列:双端队列两端都可以删除元素和追加元素的线性结构。可以很灵活的实现队列操作也可以实现栈操作,双端队列可以用双向链表实现。

循环队列结构体及宏定义如何定义

循环队列规定了一个存储空间,会出现队满的情况,循环队列解决了顺序队列假溢出的情况。这里就牵扯了到了一个问题,什么是假溢出?随着队头出队,慢慢地就会空出一个个存储单元,队尾一直在进,队头指针无法回退回去,最后就是存储空间根本没用满,但是队列提示已经满了的情况。

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #define MAX 10
  4. typedef int Typement;
  5. typedef struct queue{
  6. Typement array[MAX];
  7. int front;//指向头节点
  8. int rear;//指向尾节点
  9. }QE;

循环链表的初始化以及判断队空队满

为了防止出现假溢出我们判断队满的时候选择牺牲一个空间实现循环队列。所以这一个队列相当于长度为9的队列。当头节点和为节点指向相同坐标时,队列为空。当尾节点加1取模MAX等于头节点的坐标时,队列为满。

  1. void InitQueue(QE *Queue){//初始化队列
  2. Queue->front=0;//刚开始队列无数据头节点和尾节点指向0
  3. Queue->rear=0;
  4. }
  5. int IsEmptyQueue(QE *Queue){//判断队列是否为空,为空返回1,不为空返回0.
  6. if(Queue->rear==Queue->front){//front始终指向0,当rear==front的时候说明队列为空。
  7. printf("队列为空,无法操作!\n");
  8. return 1;
  9. }
  10. else return 0;
  11. }
  12. int IsFullQueue(QE *Queue){//判断队列是否已满,已满返回1,未满返回0.
  13. if((Queue->rear+1)%MAX==Queue->front){//牺牲了一个空间解决了假溢出情况
  14. //这里的加1再取模如果到了边界就又回到了起点 (9+1)%10=0
  15. printf("队列已满,无法操作!\n");
  16. return 1;
  17. }
  18. else return 0;
  19. }

数据入队、数据出队

理解了解决假溢出的办法之后,就很容易理解入队出队当中尾节点和头节点加1取模的含义了。这就相当于形成了一个循环,到达规定的最大值就取模返回到起点。值得注意的是,入队出队时我们首先应当判断队列的情况,是否为空,是否已满。为空不得出队,已满不得入队。

  1. void PushQueue(QE *Queue,Typement data){//数据入队
  2. if( !IsFullQueue(Queue) ){
  3. Queue->array[Queue->rear]=data;//加入数据
  4. Queue->rear=(Queue->rear+1)%MAX; //节点后移一位
  5. }
  6. }
  7. void PopQueue(QE *Queue){//数据出队
  8. if( !IsEmptyQueue(Queue) ){
  9. Queue->front=(Queue->front+1)%MAX;//头节点后移一位
  10. }
  11. }

获取队头数据、输出队列、清空队列

这些操作就相对简单了,输出队列时我们相当于利用了队空的判断条件,front==rear。只要两者不相等,就还没有输出完全。

  1. Typement GetQueue(QE *Queue){//获取队头数据
  2. if( !IsEmptyQueue(Queue) ){
  3. return Queue->array[Queue->front];
  4. }
  5. }
  6. void ShowQueue(QE *Queue){//输出队列数据
  7. if(Queue->front==Queue->rear){
  8. printf("队列为空,无数据。");
  9. return;
  10. }
  11. printf("当前队列数据为:");
  12. int i=Queue->front;
  13. while(i!=Queue->rear){
  14. printf(" %d ",Queue->array[i]);
  15. i=(i+1)%MAX;
  16. }
  17. printf("\n");
  18. }
  19. void DelQueue(QE *Queue){//清空队列
  20. Queue->rear=Queue->front;
  21. }

主函数测试

  1. int main(){
  2. QE *TextQueue=(QE*)malloc(sizeof(QE));
  3. //初始化队列
  4. InitQueue(TextQueue);
  5. //数据入队
  6. PushQueue(TextQueue,1);
  7. PushQueue(TextQueue,2);
  8. PushQueue(TextQueue,3);
  9. PushQueue(TextQueue,4);
  10. PushQueue(TextQueue,5);
  11. PushQueue(TextQueue,6);
  12. PushQueue(TextQueue,7);
  13. PushQueue(TextQueue,8);
  14. PushQueue(TextQueue,9);
  15. //获取队头数据
  16. printf("当前队头数据:%d\n",GetQueue(TextQueue));
  17. //输出队列
  18. ShowQueue(TextQueue);
  19. //数据出队
  20. PopQueue(TextQueue);
  21. PopQueue(TextQueue);
  22. PopQueue(TextQueue);
  23. PopQueue(TextQueue);
  24. PopQueue(TextQueue);
  25. PopQueue(TextQueue);
  26. printf("当前队头数据:%d\n",GetQueue(TextQueue));
  27. ShowQueue(TextQueue);
  28. //清空队列
  29. DelQueue(TextQueue);
  30. ShowQueue(TextQueue);
  31. return 0;
  32. }

测试结果

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

闽ICP备14008679号