Queue Structures
五月 29, 2021
队列(FIFO)
定义:只允许在一段插入另一端删除的 先进先出 ==排队== 线性表
- 抽象数据类型(Queue):P94~95
顺序队列 ==> 循环队列(头尾相接的改进版顺序队,解决”假溢出“)
- 队头指针:front
- 队尾指针:rear
- 队列最大尺寸:QueueSize
- 假溢出:数组中前端下标空闲,往后入队超出数组长度,非正常溢出,称为“假溢出”
- 循环队列两种判断队空队满方法
- 方法一:设置标志变量flag,front == rear,且flag=0时,队空;front == rear,且flag==1,队满
- 方法二:保留一个元素空间,front == rear,队空;数组中剩余一个空闲单位,即条件为:
(rear+1)%QueueSize == front
,队满队列长度:(rear - front + QueueSize)%QueueSize (通用长度计算公式)
- 当rear > front:rear-front
- 当rear < front:rear-front+QueueSize
循环队列顺序存储结构定义:
1
2
3
4
5
6
7typedef int QElemType;
typedef struct
{
QElemType data[MAXSIZE]; //数组存放
int front; //队头指针
int rear; //队尾指针
}SqQueue;初始化(建立)空队:
1
2
3
4
5
6Status InitQueue(SqQueue *Q)
{
Q->front = 0;
Q->rear = 0;
return OK;
}返回队列长度:
1
2
3
4int QueueLength(SqQueue Q)
{
return (Q.rear->Q.front+MAXSIZE)%MAXSIZE; //循环队通用长度计算公式
}入队:
1
2
3
4
5
6
7
8
9
10
11
12
13
14/*
1. 判断队满
2. 元素e赋值给队尾rear数据域data(排队)
3. 队尾rear后移一位,若最后一位转到头部
*/
Status EnQueue(SqQueue *Q,QElemType e)
{
if((Q.rear+1)%MAXSIZE == Q.front) //1
{
Q->data[Q->rear] = e; //2
Q->rear = (Q->rear+1)%MAXSIZE; //3
}
return OK;
}出队:
1
2
3
4
5
6
7
8
9
10
11
12
13
14/*
1. 判断队空
2. 取出队头front指针数据域赋值给*e
3. 队头front后移,若最后一位则转到头部
*/
Status DeQueue(SqQueue *Q,QElemType *e)
{
if(Q->front == Q->rear) //1
{
*e = Q->data[Q->front]; //2
Q->front = Q->front+1%MAXSIZE; //3
}
return OK;
}
链队(尾进头出的单链表)
空链队:front、rear 均指向头结点(含有)
链队列结构建立:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18typedef int QElemType;
/*
结点结构建立:
存放数据变量、next指针域
*/
typedef struct QNode
{
int data;
struct QNode *next;
}QNode,*QueuePtr;
/*
队列链表结构建立:
队头、队尾指针定义
*/
typedef struct
{
QueuePtr front, rear;
}LinkQueue;链队(队尾)入队:变动尾指针rear
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21/*
1. 动态生成新结点s
2. 异常判断:动态生成是否成功,内存溢出
3. 数据e赋值给结点s的数据域
4. 结点s指针域尾NULL,作为队尾
5. (原)尾指针rear指向的结点next指向(新结点)s
6. 尾指针rear指向新结点s
*/
Status EnQueue(LinkQueue *Q,int e)
{
QueuePtr s = (QueuePtr)malloc(sizeof(QNode)); //1
if(!s)
{
exit(OVERFLOW); //2
}
s->data = e; //3
s->next = NULL: //4
Q->rear->next = s; //5
Q->rear = s; //6
return OK;
}链队(队头)出队:变动头指针front
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26/*
1. 生成新指针变量p用于存放待删除结点
2. 异常检测:判断队空
3,队头结点(头指针的指针域next指向的结点)暂存到p
4. 取出暂存结点的数据域到*e
5. 此结点的指针域next指向的下一个结点 赋值给 头指针的指针域指向的结点,成为新的队头结点
6. 判断此结点是否为队尾(即原队列只存在一个数据),则将尾指针初始化空队(指向头结点)
7. 释放暂存结点p
*/
Status DeQueue(LinkQueue *Q,int *e)
{
QueuePtr p; //1
if(Q->rear == Q->front)
{
return ERROR; //2
}
p = Q->front->next; //3
*e = p->data; //4
Q->front->next = p->next; //5
if(Q->rear == p)
{
Q->rear = Q->front; //6
}
free(p);
return OK;
}
查看评论