经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C 语言 » 查看文章
C利用语言实现数据结构之队列
来源:jb51  时间:2021/10/8 11:08:01  对本文有异议

前言:

队列在生活中也比较常见,例如购物排队——新来的成员总是加入队尾,每次离开的成员总是队列头上的。

队列按存储方式可以分为两种:顺序队列和链队列。

一、链队列

链式队列中每个元素定义成一个结点,含数据域与指针域(指向下一结点),并设头尾指针。用图表示就是。

二、链队的表示

前面的链式结构,总是使用一个结点的结构来表示链表,但是在这里使用新的存储结构。定义一个结点结构,和一个队列结构。两个结构嵌套。

  1. //定义节点结构
  2. typedef struct QNode
  3. {
  4. QElemType data; /*数据域*/
  5. struct QNode * next; /*指针域*/
  6. }QNode, *QueuePtr;
  7. //定义队列结构
  8. typedef struct
  9. {
  10. QueuePtr front;
  11. QueuePtr rear;
  12. }LinkQueue;
  13.  

三、链队的基本操作

1. 链队的初始化

  1. Status initQueue(LinkQueue *Q)
  2. {
  3. Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));
  4. if(!Q.front) exit(OVERFLOW);
  5. Q.front->next = NULL;
  6. return OK;
  7. }
  8.  

2. 链队的销毁

  1. Status destroyQueue(LinkQueue *Q)
  2. {
  3. while (Q.front)
  4. {
  5. Q.rear = Q.front->next;
  6. free(Q.front);
  7. Q.front = Q.rear;
  8. }
  9. return OK;
  10. }
  11.  

3. 入队

  1. Status enQueue(LinkQueue *Q, QElemType e)
  2. {
  3. QueuePtr p = (QueuePtr)malloc(sizeof(QNode));
  4. if(!p) exit(OVERFLOW);
  5. //插入数据
  6. p->data = e;
  7. p->next = NULL;
  8. //Q.rear一直指向队尾
  9. Q.rear->next = p;
  10. Q.rear = p;
  11. return OK;
  12. }
  13.  

4. 出队

  1. Status deQueue(LinkQueue *Q, QElemType e)
  2. {
  3. if(Q.front == Q.rear) return ERROR;
  4. QueuePtr p = Q.front->next;
  5. e = p->data;
  6. Q.front->next = p->next; //队头元素p出队
  7. if(Q.rear == p) //如果队中只有一个元素p, 则p出队后成为空队
  8. Q.rear = Q.front; //给队尾指针赋值
  9. free(p); //释放存储空间
  10. return OK;
  11. }
  12.  

四、顺序队列

用一组连续的存储单元依次存放队列的元素,并设两个指针frontrear分别指示队头和队尾元素的位置。
front:指向实际的队头;rear:指向实际队尾的下一位置。
初态front=rear=0;队空:front=rear;队满:rear=M;
入队q[rear]=x; rear= rear+1; 出队:x=q[front];front=front+1;

顺序队列的表示:

  1. #define MAXQSIZE 100
  2. typedef struct
  3. {
  4. QElemType *base;
  5. int front; //头指针指示器
  6. int rear; //尾指针指示器
  7. } SqQueue;
  8.  

存在的问题:

随着入队、出队操作的进行,整个队列会整体向后移动,这样就出现了下图的现象:队尾指针虽然已经移到了最后,而队列却未真满的“假溢出”现象,使得队列的空间没有得到有效的利用

那我们该如何解决假溢出的问题呢?

有以下两种方法:

  • 将队中元素向队头移动:当移动数据较多时将会影响队列的操作速度。
  • 采用循环队列:Q[0]接在Q[MAXQSIZE-1]之后,一个更有效的方法是将队列的数据区Q[0 .. MAXQSIZE-1]看成是首尾相连的环,即将表示队首的元素Q[0]与表示队尾的元素Q[MAXQSIZE–1]连接起来,形成一个环形表,这就成了循环队列。当Q.rear=MAXQSIZE-1时再入队,令Q.rear=0, 则可以利用已被删除的元素空间。如下图。

五、循环队列

在循环队列中,不可以根据等式front == rear可以判别队满和队空。因为此时条件是相同的,解决这种问题的方法一般有两种。

少用(损失)一个空间,以尾指针加1等于头指针作为队满的标志。因此:当front==rear,表示循环队列为空;当front ==(rear+1)% MAXLEN,表示循环队列为满。
在定义结构体时,附设一个存储循环队列中元素个数的变量n,当n==0时表示队空;当n==MAXLEN时为队满。

循环队列的基本操作:

1. 初始化

  1. Status initQueue (SqQueue *Q)
  2. {
  3. Q.base=(QElemType *) malloc(MAXQSIZE * sizeof(QElemType));
  4. if (!Q.base) exit(OVERFLOW);
  5. Q.front = Q.rear = 0;
  6. return OK;
  7. }
  8.  

2. 求队列长度

  1. int queueLength(SqQueue *Q)
  2. {
  3. return (Q.rear - Q.front+MAXQSIZE) % MAXQSIZE;
  4. }
  5.  

3. 入队

  1. Status enQueue (SqQueue *Q, QElemType e)
  2. {
  3. if((Q.rear+1)%MAXQSIZE == Q.front) return ERROR;
  4. Q.base[Q.rear] = e;
  5. Q.rear = (Q.rear+1) % MAXQSIZE;
  6. return OK;
  7. }
  8.  

4. 出队

  1. Status deQueue (SqQueue *Q, QElemType e)
  2. {
  3. if(Q.front == Q.rear)
  4. return ERROR;
  5. e = Q.base[Q.front];
  6. Q.front = (Q.front+1)%MAXQSIZE;
  7. return OK;
  8. }

到此这篇关于C利用语言实现数据结构之队列的文章就介绍到这了,更多相关C语言实现数据结构 队列内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号