循环队列的顺序存储
2016-03-20 10:57
351 查看
在学习队列的过程中,我积累了一些更好的分析问题的方法,现加以总结,如下:
1.对于队列的顺序存储结构,如果要将第一个元素存在数组的第一个位置,则之后在插入和删除时平均要移动n个元素,时间复杂度为O(n);细细想来,其实不把第一个元素放在第一个位置上也可以,这种方案不仅仅是增强了灵活性,更重要的是它解决了插入删除过程中移动n个元素的问题;由于第一个元素不需要在第一个位置上,队首指针和队尾指针的前后顺序并没有明确的规定(或者说队首指针不一定要在队尾指针的前面) 每当队尾指针到队尾时,就让队尾指针重新回到队首,如果队首还有空间就让新数据存入队首的空间中;这样能够避免因队尾指针到末端无空间后(实际上前端还有空间)造成的”假溢出”现象;
那么队尾指针循环移动是如何做到的呢?答案十分巧妙:rear=(rear+1)%maxsize;
2.循环队列如何判断队列已满呢?;我想到的第一种方法:队首指针==队尾指针且不为0。但细想之后发现不妥,既然队首指针不一定要在队尾指针的前面,那么队首==队尾时也不一定意味着满队列;在参阅书籍之后,我发现了一种巧妙地办法:当队列满时,保留一个元素空间。
那么如何用C语言实现呢,如下:(rear+1)%maxsize==front;
3.第三个问题,循环队列在带来了诸多的好处的同时,由于其指针的灵活性与不确定性,其长度变得难以求解;下面给出循环队列长度公式length=(rear-front+maxsize)%maxsize
有了上述三点,循环队列就变得十分容易处理且便于使用了;
1.对于队列的顺序存储结构,如果要将第一个元素存在数组的第一个位置,则之后在插入和删除时平均要移动n个元素,时间复杂度为O(n);细细想来,其实不把第一个元素放在第一个位置上也可以,这种方案不仅仅是增强了灵活性,更重要的是它解决了插入删除过程中移动n个元素的问题;由于第一个元素不需要在第一个位置上,队首指针和队尾指针的前后顺序并没有明确的规定(或者说队首指针不一定要在队尾指针的前面) 每当队尾指针到队尾时,就让队尾指针重新回到队首,如果队首还有空间就让新数据存入队首的空间中;这样能够避免因队尾指针到末端无空间后(实际上前端还有空间)造成的”假溢出”现象;
那么队尾指针循环移动是如何做到的呢?答案十分巧妙:rear=(rear+1)%maxsize;
2.循环队列如何判断队列已满呢?;我想到的第一种方法:队首指针==队尾指针且不为0。但细想之后发现不妥,既然队首指针不一定要在队尾指针的前面,那么队首==队尾时也不一定意味着满队列;在参阅书籍之后,我发现了一种巧妙地办法:当队列满时,保留一个元素空间。
那么如何用C语言实现呢,如下:(rear+1)%maxsize==front;
3.第三个问题,循环队列在带来了诸多的好处的同时,由于其指针的灵活性与不确定性,其长度变得难以求解;下面给出循环队列长度公式length=(rear-front+maxsize)%maxsize
有了上述三点,循环队列就变得十分容易处理且便于使用了;
#include<stdio.h> #include<stdlib.h> #include<time.h> #define ERROR 0 #define OK 1 #define TRUE 1 #define FALSE 0 #define maxsize 20 typedef int status; typedef int elemtype; /*定义队列*/ typedef struct queue{ elemtype data[maxsize]; int front;//定义队首指针 int rear;//定义队尾指针 }queue; status visit(elemtype c){ printf("%d ",c); return OK; } /*初始化队列*/ status initqueue(queue *Q){ Q->front=0;/*让队首队尾指针全部为0,为空队列状态*/ Q->rear=0; return OK; } /*判断队列是否为空*/ status emptyqueue(queue *Q){ if(Q->front==Q->rear)/*队列为空的条件是Q->front==Q->rear,而队列满的条件是(Q->rear+1)%maxsize==Q->front*/ printf("空队列\n"); } /*返回队列长度*/ status queuelength(queue *Q){ return (Q->rear-Q->front+maxsize)%maxsize;/*此为队列长度计算公式*/ } /*判断是否满队列*/ status fullqueue(queue *Q){ if((Q->rear+1)%maxsize==Q->front){/*队列满的条件是(Q->rear+1)%maxsize==Q->front,意思是rear和front只差1个单位*/ return TRUE; } else{ return FALSE; } } /*入队列*/ status enterqueue(queue *Q,elemtype data){ if((Q->rear+1)%maxsize==Q->front){ printf("队列已满\n"); return ERROR; } Q->data[Q->rear]=data;/*把元素赋值给Q->data数组,同时队尾指针后移*/ Q->rear=(Q->rear+1)%maxsize;/*此处不写Q->rear++的原因是:如果队首指针不在队列开始处,容易造成队首还有若干个空间而却误认为队列已满 ,形成"假溢出”*/ return OK; } status exitqueue(queue *Q,elemtype data){ if(Q->front==Q->rear){ printf("空队列\n"); return ERROR; } data=Q->data[Q->front];/*出队列时从队首指针指向的元素开始*/ printf("%d ",data); Q->front=(Q->front+1)%maxsize;/*队首指针后移,若队首指针在队尾指针之后(存在此种可能,切记!!),则在越过队列末端后 重新回到队列首端*/ } status traversequeue(queue *Q){ int i=Q->front; while(i!=Q->rear){/*用于判断是否达到了队列末端*/ visit(Q->data[i]); i=(i+1)%maxsize; } return OK; } int main(void){ queue Q; elemtype e; initqueue(&Q); emptyqueue(&Q); printf("队列长%d\n",queuelength(&Q)); printf("入队列 "); for(int i=0;i<maxsize-1;i++){ enterqueue(&Q,i); } traversequeue(&Q); printf("\n"); printf("删除队列首端两个元素\n"); for(int i=0;i<2;i++){ exitqueue(&Q,e); } printf("\n"); printf("出队列:"); for(int i=0;i<maxsize-3;i++){ exitqueue(&Q,e); } printf("\n"); printf("队列长为%d\n",queuelength(&Q)); initqueue(&Q); printf("清空队列后,"); emptyqueue(&Q); printf("队列长为%d\n",queuelength(&Q)); }
相关文章推荐
- 使用Scala实现Java项目的单词计数:串行及Actor版本
- 《Linux内核设计与实现》读书笔记 第五章 系统调用
- bootstrap兼容IE8的一些注意
- C语言两种定义字符串的方式
- [置顶] Hadoop核心组件之HDFS
- TrustZone初探(一)
- win7+visual studio2010+Opencv配置
- PHP数据类型转换和运算符表达式
- NFS服务的搭建
- YMS Round #1 Div. 2 D Subsequences Summing to Sevens
- poj1033 模拟(dfs)
- Subset II [Leetcode 解题报告]
- opencv k-means
- YMS Round #1 Div. 2 C Mowing the Field
- 《生活不止眼前的苟且》 --许巍
- 从源代码生成可执行程序
- Java实现文件的读取操作
- 计算2的任意次方[通用版]
- OpenCL: kernel中的向量关系运算符和等价运算符(>,<,>=,<=,==,!=)
- IOS 屏幕遮罩 Mask