定义
只能在表的一端进行插入运算,在表的另一端进行删除运算的线性表
逻辑结构
与同线性表相同,仍为一对一关系
存储结构
顺序队或链队,以循环顺序队列更常见
运算规则
只能在队首和队尾运算,且访问结点时按照先进先出的原则
实现方式
关键是掌握入队和出队的操作,具体实现依照顺序队或链队而不同
队列的常见应用
- 脱机打印输出:按申请的先后顺序输出
- 多用户系统中,多个用户排成队,分时地循环使用cpu和主存
- 实时控制系统中,信号按接收的先后顺序依次处理
- 网络电文传输,按到达的时间先后顺序运行
队列的抽象数据类型定义
ADT Quene{
数据对象:D = {ai|ai∈ElemSet,i=1,2,…,n,n>=0)
数据关系:R = {<ai-1,ai>|ai-1,ai∈D,i=2,…,n) 约定其中a1端为队列头,an端为队列尾
基本操作:
InitQueue (&Q) 操作结果:构造空队列Q
DestroyQueue (&Q) 条件:队列Q已存在;操作结果:队列Q被销毁
ClearQueue (&Q) 条件:队列Q已存在;操作结果:将Q清空
QueueLength (Q) 条件:队列Q已存在;操作结果:返回Q的元素个数,即队长
GetHead (Q,&e) 条件:Q为非空队列;操作结果:用e返回Q的队头元素
EnQueue (&Q,e) 条件:队列Q已存在;操作结果:插入元素e为Q的队尾元素
DeQueue (&Q,&e) 条件:Q为非空队列;操作结果:删除 Q 的队头元素,用 e 返回值
…还有将队列置空、遍历队列等操作…
} ADT Queue
队列的物理存储可以用顺序存储结构,也可以用链式存储结构。相应的,队列的存储方式也分为两种,即顺序队列和链式队列
队列的顺序表示——用一维数组base[MAXQISE]
#define MAXQSIZE 100 //最大队列长度
Typedef struct{
QElemType *base; //初始化的动态分配内存空间
int front; //头指针
int rear; //尾指针
}SqQueue;
解决假上溢方法
将队中元素依次向对头方向移动
缺点:浪费时间,每移动一次,队中元素都要移动
引入循环队列
base[0]接在base[MAXQISE-1]之后,若rear+1==M,则令rear=0
实现方法
利用模(mod,C语言中:%)运算
插入元素:Q.base[Q.rear]=x
Q.rear=(Q.rear+1)%MAXQSISE
删除元素:x=Q.base[s.front]
Q.front=(Q.front+1)%MAXQSISE
如何判断队空队满
解决方案
另外设一个标志以区别队空、队满
另设一个变量,记录元素个数
少用一个元素空间
队空:front==rear
队满:(rear+1)%MAXQSIXSE==front
队列的初始化
Status InitQueue(SqQueue &Q){
Q.base = new QElemType[NAXQSEZE] //分配数组空间
//Q.base = (QElmType*)
//malloc(MAXQSISE*sezeof(QElemTy03));
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==!.front) return ERROR; //队满
Q.base[Q.rear]=e; //新元素加入队尾
Q.rear=(Q.rear+1)%MAXQSIZE; //队尾指针+1
return OK;
}
循环队列出队
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;
}
取队头元素
QElemType GetHead(SqQueue Q){
if(Q.front!=Q.rear) //队列不为空
return Q.base[Q.front]; //返回队头指针元素的值,队头指针不变
}
队列的链式表示和实现
若用户无法估计所用队列的长度,则宜采用链队列
链队列的类型定义
#define MAXQSIZE 100 //最大队列长度
typedef struct Qnode{
QElemType data;
stuct Qnode *next;
}QNode,*QuenePtr;
typedef struct{
QuenePtr front; //队头指针
QuenePtr 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 DestroyQueue(LinkQueue &Q){
while(Q.front){
p=Q.front->next;
free(Q.front);
Q.front=p;
}
return OK;
}