4. 队列
队列是限定插入在表尾和删除在表头进行的线性表。
ADT Queue {
数据对象:
D={ai | ai∈ElemSet, i=1,2,...,n, n≥0}
数据关系:
R1={ <a i-1,ai > | ai-1, ai ∈D, i=2,...,n} //约定其中a1 端为队列头, an 端为队列尾
基本操作:
InitQueue(&Q) DestroyQueue(&Q)
QueueEmpty(Q) QueueLength(Q)
GetHead(Q, &e) ClearQueue(&Q)
EnQueue(&Q, e) DeQueue(&Q, &e)
QueueTravers(Q, visit())
} ADT Queue
InitQueue(&Q)//操作结果:构造一个空队列Q。
DestroyQueue(&Q)//初始条件:队列Q已存在。操作结果:队列Q被销毁,不再存在。
ClearQueue(&Q)//初始条件:队列Q已存在。操作结果:将Q清为空队列。
4.1 队列的链式实现
介绍队列的链表实现方式
typedef struct QNode { // 结点类型
QElemType data;
struct QNode *next;
} QNode, *QueuePtr;
typedef struct { // 链队列类型
QueuePtr front; // 队头指针
QueuePtr rear; // 队尾指针
} LinkQueue;
//链队列的初始化
Status InitQueue(LinkQueue &Q){
//构造一个空队列Q
Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));
if(!Q.front)exit(OVERFLOW);//存储分配失败
Q.front->next=NULL;
return OK;
}
//链队列的删除
Status DeQueue(LinkQueue &Q, QElemType &e){
//若队列不为空,则删除Q的队头元素
//用e返回其值,并返回OK,否则返回ERROR
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;
free(p); return OK;
}
4.2 队列的顺序实现
#define MAXQSIZE 100 //最大队列长度
typedef struct {
QElemType *base; // 动态分配存储空间
int front; // 头指针,若队列不空,指向队列头元素
int rear; // 尾指针,若队列不空,指向队列尾元素的下一个位置
} SqQueue;
//循环队列的插入
Status EnQueue (SqQueue &Q, ElemType e) { // 插入元素e为Q的新的队尾元素
if ((Q.rear+1) % MAXQSIZE == Q.front)
return ERROR; //队列满
Q.base[Q.rear] = e;
Q.rear = (Q.rear+1) % MAXQSIZE;
return OK;
}
//循环队列的删除
Status DeQueue (SqQueue &Q, ElemType &e) { // 若队列不空,则删除Q的队头元素,
// 用e返回其值,并返回OK; 否则返回ERROR
if (Q.front == Q.rear) return ERROR;
e = Q.base[Q.front];
Q.front = (Q.front+1) % MAXQSIZE;
return OK;
}
//循环队列的长度
4.2.1 例题
1.循环队列存储在数组A[0…9]中,其头、尾指针分别是front=3和rear=1,则队列中的元素个数为__8___。
- 设数组A[m]作为循环队列sq的存储空间,front为队头指针,rear为队尾指针,则执行出队操作时修改指针的语句是(A)。
sq.front=( sq.front+1)%m
sq.front=( sq.front+1)%(m+1 )
sq.rear=( sq.rear+1)%m
sq.rear=( sq.rear+1)%(m+1)
4.2.2 斐波那契序列
试利用循环队列编写求k阶斐波那契序列中前n+1项(f0, f1 , f2 ,… fn )的算法,要求满足fn ≤max而fn+1 >max ,其中max为某个约定的常数。f0=0 , f1=0 , …, fk-2=0 , fk-1=1, fn = fn-1 + fn-2 +…+ fn-k (n=k,k+1,…)
算法思路:用数组f[i]存放斐波那契数列的第i项,循环队列 cq[0…k-1] 存放f(n-k)到f(n-1)的值。所以斐波那契额的第K项=循环队列中所有元素之和。
void fb(int k)
{ int i,j;
for(i=0;i<=k-2;i++) { f[i]=0 ; cq.elem[i]=0 ; } //为前k-1个元素赋初值0,并放入队列cq
cq.elem[k-1]=f[k-1]=1; //为第k个元素赋值,并放入队列cq
cq.rear=k-1; n=k;
while(cq.elem[cq. rear]<max) //利用循环队列依次求f[n]
{f[n]=0;
for(j=0;j<k;j++) f[n]=f[n]+cq.elem[j];
cq.rear=(cq.rear +1) % k;
cq.elem[cq.rear]=f[n];
n++;
} //利用循环队列依次求f[n]
if(cq.elem[cq.rear]>max) n=n-2; else n=n-1;
}