链队通常用单链表来表示。所以需要两个分别用来指向队头和队尾的指针。为了便于插入和判断链队的队空(没有队满),还需要增加一个头结点。初始化是使头指针和尾指针都指向头结点,表示队空。
链队的存储结构:
typedef int QElemType;
typedef struct QNode{
QElemType data;
struct QNode *next;
}QNode,*QueuePtr; //结点结构体,用来增加结点。
typedef struct{
QueuePtr Front;
QueuePtr Rear;
}*LinkQueue,Queue; //存放指针的结构体
第一个结构体用来是结点结构体,用来申请增加结点。
第二个是指针结构体,存放指针。
如图所示,链队的逻辑结构,头指针和尾指针的位置。
一、初始化
Status InitQueue(LinkQueue Q){
Q=(LinkQueue)malloc(sizeof(Queue)); //申请空间存放指针。
if(Q==NULL)
return ERROR;
Q->Rear=Q->Front=(QueuePtr)malloc(sizeof(QNode));
/*生成新结点作为头结点,队头和队尾指针指向此结点,表示队空*/
Q->Front->next=NULL; //头指针的指针域为NULL
return OK;
}
1、申请指针结点 2、申请一个头结点,头结点与尾结点指向此结点 3、头结点指针域为空。
二、入队
Status EnQueuq(LinkQueue Q,QElemType e){
QueuePtr p;
p=(QueuePtr)malloc(sizeof(QNode));/为入队元素分配结点空间,用指针p指向
p->data=e; //赋值
p->next=NULL; //指针域为NULL
Q->Rear->next=p; //将新结点插入到队尾
Q->Rear=p; //修改尾指针
return OK;
}
1、申请结点 2、存放数据,指针域置NULL 3、将新结点插入到队尾,并修改为指针。(就是链表的尾插法)
三、出队
Status DeQueue(LinkQueue Q,QElemType *e){
if(Q->Rear==Q->Front) //判断是否栈空
return ERROR;
QueuePtr p;
p=Q->Front->next; //p指向队头结点
*e=p->data; //取值
Q->Front->next=p->next; //将队头结点指针域赋值给头结点指针域
if(Q->Rear==p) //判断尾指针指向的尾队尾结点是不是头结点(是不是只有一个结点)
Q->Rear=Q->Front; //若是则尾指针指向头指针
free(p); //释放队头结点
return OK;
}
1、记录先对头结点的地址 2、取值 3、出队 4、判断是否只有一个结点 5、释放队头结点
如果不判断的话,若只有一个结点,释放了这个结点,为指针就不知道指向哪里了,理论上应该是队空,但是没有零Q->Rear=Q->Front,所以无法判断。
四、取头元素
Status GetHead(LinkQueue Q,QElemType *e){
if(Q->Rear!=Q->Front){
*e=Q->Front->next->data;
return OK;
}