【正确答案】
【答案解析】在队列的顺序存储结构中,除了使用一组地址连续的存储单元依次存放从队列头到队列尾的元素之外,还需要另外设置两个指针front和rear分别指示队列头元素以及队列尾元素的位置。初始化建空队列时,令front=rear=0,每当插入新的队列尾元素时,“尾指针增1”,而每当删除队列头元素时,则执行“头指针增1”。因此,在非空队列中,头指针始终指向队列头元素,尾指针始终指向队列尾元素的下一个位置。
为充分利用向量空间,克服“假溢出”现象的方法是:将向量空间想象为一个首尾相接的圆环,并称这种向量为循环向量。存储在其中的队列称为循环队列(Circular Queue)。循环队列中,由于入队时尾指针向前追赶头指针;出队时头指针向前追赶尾指针,造成队空和队满时头尾指针均相等。因此,无法通过条件front==rear来判别队列是“空”还是“满”。
解决这个问题的方法至少有两种:
1)另外设置一个标志位来区别队列是“空”还是“满”。
2)少用一个元素空间,约定以“队列头指针在队列尾指针的下一位置(指环状的下一位置)”上作为队列呈“满”状态的标志。队满时:(rear+1)%n=front,n为队列长度(所用数组大小),由于rear、front均为所用空间的指针,循环只是逻辑上的循环,所以需要求余运算。
算法示例如下:
#define MAXSIZE 1000
typedef int ElemType;
typedef struct
{
ElemType data[MAXSIZE];
int front;
int rear;
}CircSeqQueue;
∥顺序循环队列的初始化
void QueueInitial(CircSeqQueue *pQ)
{
pQ->front=pQ->"rear=0;
}
∥顺序循环队列判空
int IsEmpty(CircSeqQueue *pQ)
{
return pQ->front==pQ->rear;
}
∥顺序循环队列判满
int IsFull(CircSeqQueue *pQ)
{
return (pQ->rear+1)%MAXSIZE= =pQ->front;
}
∥元素进队列
void EnQueue(CircSeqQueue *pQ,ElemType e)
{
if(IsFull(pQ))
{
printf("列队溢出!/n");
exit(1);
pQ->rear=(pQ->rear+1)%MAXSIZE;
pQ->data[pQ->rear]=e;
∥元素出队列
ElemType DeQueue(CircSeqQueue *pQ)
{
if(IsEmpty(pQ))
{
printf("空队列!/n");
exit(1);
}
pQ->front=-(pQ->front+1)%MAXSIZE;
return pQ->data[pQ->front];
}
∥取对头元素
ElemType GetFront(CircSeqQueue *pQ)
{
if(IsEmpty(pQ))
{
printf("队列为空!/n");
exit(1);
}
return pQ->data[(pQ->front+1)%MAXSIZE];
}
∥循环队列置空
void MakeEmpty(CircSeqQueue *pQ)
{
pQ->front=pQ->rear=0;