赞
踩
目录
特点
是一个特殊的线性表,在表一端插入(表尾),在另一端(表头)删除。
队列 又称为 先进先出(First In First Out)的线性表,简称FIFO结构。
表尾称为 队尾 Top,表头称为 队头 Base。
插入元素到 队尾 的操作,称为 入队。
从 队头 删除第一个元素的操作,称为 出队。
逻辑结构
与线性表相同,仍为一对一关系。
存储结构
顺序队 或 链队,以循环顺序队列更常见。
实现方式
主要是入队和出队函数,链队和顺序队不同。
队列的顺序存储:同一般线性表的顺序存储结构完全相同。
和栈不太一样的是,队列的头,尾指针都需要移动,以循环顺序队列为常见。
- #define MAXQSIZE 100 //最大队列长度
- typedef struct {
- QElemType *base;//初始化的动态分配存储空间
- int front; //头“指针”
- int rear; //尾“指针”
- }SqQueue;
这里的头尾指针存放的不是真正意义上的指针,而是数组下标,是一个整数,目的是为了方便操作。
溢出:
加溢出:当rear = MAXQSIZE但front不为0时,是假溢出。
真溢出:当rear = MAXQSIZE且front为0时,还要入队,是真溢出。
解决假溢出的方法是引入 循环队列。
将b[0]接在b[MAXQSIZE-1]之后。
方法:用%运算。
所以当我们入队时,不再是
- Q.base[Q.rear] = x;
- Q.rear++;
而是
- Q.base[Q.rear] = x;
- Q.rear = (Q.rear+1)%MAXQSIZE;
同样,出队时,不再是
- x = Q.base[Q.front];
- Q.front++;
而是
- x = Q.base[Q.front];
- Q.front = (Q.front+1)%MAXQSIZE;
但此时又出现了一个新的问题——队空和队满的条件都为
Q.rear == Q.front;
那么如何分辨是队空还是队满呢?
有三种方案:
另设一个标志以区别队空、队满。
另设一个变量,记录元素个数。(设置一个计数器)
少用一个元素空间。(常用)
用了第三种方案后:
队空:Q.front == Q.rear;
队满:(Qrear+1)%MAXSIZE == Q.front;
于是解决。
算法描述:
- Status InitQueue(SqQueue &Q) {
- Q.base = new QElemType[MAXQSIZE];//分配空间
- if(!Q.base) exit(OVERFLOW); //存储分配失败
- Q.front = Q.rear = 0; //头尾指针置为0,队列为空
- return OK;
- }
算法描述:
- int QueueLength(SqQueue Q) {
- return (Q.rear - Q.front + MAXQSIZE)%MAXQSIZE;
- }
算法思路:
判断是否栈满
元素插入队尾
尾指针+1
算法描述:
- Status EnQueue(SqQueue &Q, QElemType e) {
- if((Q.rear+1)%MAXQSIZE == Q.front) return ERROR; //队满
- Q.base[Q.rear] = e; //元素插入队尾
- Q.rear = (Q.rear+1)%MAXQSIZE; //尾指针+1
- return OK;
- }
算法思路:
判断是否栈空
元素出队
头指针+1
算法描述:
- Status DeQueue(SqQueue &Q, QElemType &e) {
- if(Q.front == Q.rear) return ERROR; //队空
- e = Q.base[Q.front]; //保存头元素
- Q.front = (Q.front+1)%MAXQSIZE; //队头指针+1
- return OK;
- }
算法描述:
- SElemType GetHead(SqQueue Q) {
- if(Q.front != Q.rear) //队列不为空
- return Q.base[Q.front]; //返回队头指针元素的值,队头指针不变
- }
链栈不需要头结点,链队列需要头结点。
结点的定义:
- #define MAXQSIZE 100 //最大队列长度
- typedef struct Qnode {
- QElemType data;
- struct Qnode *next;
- } QNode, *QueuePtr;
头尾指针的定义:
- typedef struct {
- QueuePtr front;//队头指针
- QueuePtr rear;//队尾指针
- } LinkQueue;
当 LinkQueue Q; 后就可以和之前一样用Q.front,Q.rear进行操作了。
算法描述:
- Status InitQueue(LinkQueue &Q) {
- Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));
- if(!Q.front) exit(OVERFLOW); //一般不用判断
- Q.front->next = NULL;
- return OK;
- }
算法思路:从头开始依次释放。
算法描述:
- Status DestroyQueue(LinkQueue &Q) {
- while(Q.front) {
- p = Q.front->next;
- free(Q.front);
- Q.front = p;
- }//Q.rear = Q.front->next; free(Q.front) ; Q.front = Q.rear;
- return OK;
- }
算法思路:
生成新节点p
e存进p->data
修改队尾指针
算法描述:
- Status EnQueue(LinkQueue &Q, QElemType e) {
- p = (QueuePtr)malloc(sizeof(QNode));
- if(!p) exit(OVERFLOW);
- p->data = e; p->next = NULL;
- Q.rear->next = p;
- Q.rear = p;
- return OK;
- }
算法思路:
保存首元结点地址(可以顺便把data用e返回)
修改队头指针
释放之前的首元结点
算法描述:
- Status DeQueue(LinkQueue &Q, QElemType &e) {
- if(Q.front == Q.rear) return ERROR;
- p = Q.front->next;
- e = p->data;
- Q.front->next = p->next;
- if(Q.rear == p) Q.rear = Q.front;
- delete p;
- return OK;
- }
算法描述:
- Status GetHead(LinkQueue Q, QElemType &e) {
- if(Q.front == Q.rear) return ERROR;
- e = Q.front->next->data;
- return OK;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。