设为首页 加入收藏

TOP

队列的存储结构和常见操作(c 语言实现)(二)
2014-11-23 20:00:08 来源: 作者: 【 】 浏览:7
Tags:队列 存储 结构 常见 操作 语言 实现
ue(&queue, 2);
14 insertQueue(&queue, 3);
15 traversal(queue);
16
17 puts("先进先出,删除队列从头开始, 0 ");
18 deleteQueue(&queue);
19 traversal(queue);
20
21 puts("先进先出,删除队列从头开始, 1 ");
22 deleteQueue(&queue);
23 traversal(queue);
24
25 puts("先进先出,删除队列从头开始, 2 ");
26 deleteQueue(&queue);
27 traversal(queue);
28
29 puts("先进先出,删除队列从头开始, 3");
30 deleteQueue(&queue);
31 traversal(queue);
32
33 destoryQueue(&queue);
34 return 0;
35 }
复制代码
结果:
初始化队列 queue
队尾依次插入0 1 2 3
队列第1个元素是:0
队列第2个元素是:1
队列第3个元素是:2
队列第4个元素是:3
先进先出,删除队列从头开始, 0
队列第1个元素是:1
队列第2个元素是:2
队列第3个元素是:3
先进先出,删除队列从头开始, 1
队列第1个元素是:2
队列第2个元素是:3
先进先出,删除队列从头开始, 2
队列第1个元素是:3
先进先出,删除队列从头开始, 3
销毁成功!
Program ended with exit code: 0
3、顺序队列
限制仅在表头删除和表尾插入的顺序表,利用一组地址连续的存储单元依次存放队列中的数据元素。因为队头和队尾的位置是变化的,所以也要设头、尾指针。
初始化时的头尾指针,初始值均应置为 0。 入队尾指针增 1 ,出队头指针增 1 。头尾指针相等时队列为空,在非空队列里,头指针始终指向队头元素,尾指针始终指向队尾元素的下一位置。
初始为空队列,那么头尾指针相等。
入队,那么尾指针加1,头指针不变。先进先出,J1先进队,则 rear+1,尾指针始终指向队尾元素的下一位!如,J2进队,rear 继续+1,J3进队,尾指针继续加1,如图
出队,则尾指针不变,头指针加1,注意这里都是加1,先进先出原则,J1先删除,front+1,指向了 J2,J2删除,front+1指向了 J3,如图
最后,J3删除,则头指针再次和尾指针相等,说明队列空了。如图
在顺序队列中,当尾指针已经指向了队列的最后一个位置的下一位置时,若再有元素入队,就会发生“溢出”。如图位置,再次入队,就会溢出。
4、循环队列的诞生
顺序队列的 “假溢出” 问题:队列的存储空间未满,却发生了溢出。很好理解,比如 rear 现在虽然指向了最后一个位置的下一位置,但是之前队头也删除了一些元素,那么队头指针经历若干次的 +1 之后,遗留下了很多空位置,但是顺序队列还在傻乎乎的以为再有元素入队,就溢出呢!肯定不合理。故循环队列诞生!
解决“假溢出”的问题有两种可行的方法:
(1)、平移元素:把元素平移到队列的首部。效率低。否决了。
(2)、将新元素插入到第一个位置上,构成循环队列,入队和出队仍按“先进先出”的原则进行。操作效率高、空间利用率高。
虽然使用循环队列,解决了假溢出问题,但是又有新问题发生——判空的问题,因为仅凭 front = rear 不能判定循环队列是空还是满。比如如图:
这是空循环队列的样子
这是满循环队列的样子
解决办法:
(1)、另设一个布尔变量以区别队列的空和满;
(2)、少用一个元素的空间,约定入队前测试尾指针在循环下加 1 后是否等于头指针,若相等则认为队满;(最常用)
(3)、使用一个计数器记录队列中元素的总数。
对于第2个方案,必须牺牲一个元素的空间,那么入队的时候需要测试,循环意义下的加 1 操作可以描述为:
复制代码
1 if (rear + 1 = MAXQSIZE)
2
3 rear = 0;
4
5 else
6
7 rear ++;
复制代码
利用模运算可简化为:
1 rear = (rear + 1)% MAXQSIZE
基本操作
复制代码
1 #ifndef ___queue_Header_h
2 #define ___queue_Header_h
3 #include
4 #include
5 #define MAX_SIZE 5
6
7 typedef struct{
8 int *base;
9 int rear;//如果队列不空,指向队尾元素的下一个位置
10 int front;//初始的时候指向表头
11 } CirularQueue;
12
13 //初始化
14 void initQueue(CirularQueue *queue)
15 {
16 queue->base = (int *)malloc(MAX_SIZE*sizeof(int));
17
18 if (NULL == queue->base) {
19 exit(0);
20 }
21
22 queue->front = queue->rear = 0;
23 }
复制代码
求长度
复制代码
//求长度
int getLength(CirularQueue queue)
{
//这样把所以的情况都考虑到了
return (queue.rear - queue.front + MAX_SIZE) % MAX_SIZE;
}
复制代码
第一种情况,长度的求法
第二种情况,长度的求法,利用模运算,两个情况合二为一!
复制代码
//入队,先判满
void insertQueue(CirularQueue *queue, int e)
{
if ((queue->rear + 1) % MAX_SIZE == queue->front) {
puts("循环队列是满的!");
}
else
{
queue->bas
首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇栈的存储结构和常见操作(c 语言.. 下一篇Objective-C基础笔记(5)Protocol

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: