队列的链式存储结构实现称作链队列。与链栈相似,链队列实际上也是单链表。为了操作上的方便,根据队列的FIFO特点,需要设队头和队尾两个指针,并把这两个指针封装在同一个结构体内;此外,常采用带头结点的单链表,使得队空与非空具有同一结构形式。
链队列的类型定义如下:
typedef struct node
{
elemtype data;
struct node *next;
}linknode;//定义链队列中的结点类型
typedef struct
{
linknode *front,*rear;
}linkqueue;//定义将头尾指针封装在一起的链队列类型
linkqueue *q;
在这个定义之下,链队列的几种基本运算的算法描述如下:
1.初始化算法:
void iniqueue(linkqueue *q)//设置空的链队列
{
q->front=(linknode *)malloc(sizeof(linknode));//产生一个头结点并将地址填入头指针域
q->rear=q->front;//让尾指针也指向头结点
q->front->next=NULL;//填头结点的next域为空
}
2.入队列算法
void addqueue(linkqueue *q,elemtype x)//把元素x插入链队列q之中
{
linknode *P;
p=(linknode *)malloc(sizeof(linknode));//产生一个新结点
p->data=x;//填入元素值
p->next=NULL;//指针域填NULL
q->rear->next=p;//新结点插入队尾
q->rear=p;//修改队尾指针
}
3.出队列算法
出队列是要删除队列中第一个元素结点并返回其值,当队列为空时返回NULL。当队列非空时,一般只需让第一个元素结点的next域值填入头结点next域即可;但当队列中只有一个结点时,还要修改队尾指针使其指向头结点。
为了避免在只有一个元素结点时与多结点时操作不一致需修改队尾指针,算法中删除的是头结点而不是第一个元素结点,让第一个元素结点作为删除后的头结点,而在逻辑上达到了删除第一个结点的目的(它成为新的头结点了);带来的好处是队列非空时的操作上的一致性。
算法描述如下:
elemtype outqueue(linkqueue *q)//删除队头元素并返回其值
{
linknode *p;
if(q->rear==q->front)//队列为空时返回NULL
return NULL;
else
{
p=q->front;//p指向头结点
q->front=q->front->next;//让第一个元素结点成为新的头结点
free(p);
return q->front->data;//返回原第一个元素结点的值,它在新的队头结点中保存着
}
}
4.读队头元素
elemtype gethead(linkqueue *q)//读队头元素并返回其值
{
if(q->rear==q->front)
return NULL;//队列为空返回NULL
else
return q->front->next->data;//队列非空返回第一个元素结点data域的值
}
5.判队列空
int empty(sequeue *q)//当队列q为空时返回1否则返回0
{
if(q->rear==q->front)
return 1;
else
return 0;
}