队列的表示和操作的实现
队列的概念
队列(Queue):
只能在表的一端进行插入运算,在表的另一端进行删除运算的线性表(头删尾插)
逻辑结构:
和线性表相同,仍为一对一的关系
存储结构:
顺序队或链队,以循环顺序队列更常见
运算规则:
只能在队首或队尾运算,且访问结点时依照先进先出(FIFO)的原则
实现方式:
关键是掌握入队和出队操作,具体实现依顺序队或链队的不同而不同
队列的顺序表示和实现
解决假上溢的方法——引入循环队列
循环队列的类型定义:
#define MAXQSIZE 100 //最大队列长度
Typedef struct{
QElemType *base; //初始化的动态分配存储空间
int front; //头指针,若队列不为空,指向队列头元素
int rear; //尾指针,若队列不空,指向队列尾元素的下一位置
}SqQueue;
队空:front == rear
循环队列解决队满时判断方法——少用一个元素空间
队满:(rear+1)%MAXQSIZE == front
队列的初始化:
Status InitQueue(SqQueue &Q){
Q.base = new QElemType[MAXQSIZE]; //分配数组空间
//Q.base = (QElemType*)malloc(MAXQSIZE*sizeof(QElemType));
if(!Q.base)
exit(OVERFLOW); //存储分配失败
Q.front = Q.rear = 0; 头指针尾指针置为0,队列为空
return OK;
}
求队列的长度:
int QueueLength(SqQueue Q){
return (Q.rear - Q.front + MAXQSIZE)%MAXQSIZE
}
循环队列的入队:
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;
}
ps: base是数组,Q.rear是int型
循环队列的出队:
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;
链队列的初始化:
Status InitQueue(LinkQueue &Q){
Q.front = Q.rear =(QueuePtr)malloc(sizeof(QNode));
if(!Q.front)
exit(OVERFLOW);
Q.front -> next = NULL;
return OK;
}
链队列运算指针变化状况:
链队列的销毁:
Status DestoryQueue(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;
}
将元素e入队:
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;
}
链队列出队:
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;
}