链队列是采用链式存储结构实现的队列,通常链队列用单链表来表现。一个队列要入队和出队,所以要有个头指针(队头)和尾指针(队尾),入队时运用尾指针,出队时运用头指针。以下是链队列代码实现和实现结果:
#include<stdio.h>
#include<stdlib.h>
typedef struct LinkNode {
int data;
struct LinkNode* next;
}*LinkNodePtr;
typedef struct LinkQueue {
LinkNodePtr front;
LinkNodePtr rear;
}*LinkQueuePtr;
LinkQueuePtr initQueue()
{
LinkQueuePtr resultPtr = (LinkQueuePtr)malloc(sizeof(struct LinkQueue));
LinkNodePtr headerPtr = (LinkNodePtr)malloc(sizeof(struct LinkNode));
headerPtr->data = 0;
headerPtr->next = NULL;
resultPtr->front = headerPtr;
resultPtr->rear = headerPtr;
return resultPtr;
}//off initQueue
void outputLinkQueue(LinkQueuePtr paraQueuePtr)
{
LinkNodePtr tempPtr = paraQueuePtr->front->next;
while (tempPtr != NULL)
{
printf("%d ", tempPtr->data);
tempPtr = tempPtr->next;
}//off while
printf("\r\n");
}//off outputLinkQueue
void enqueue(LinkQueuePtr paraQueuePtr, int paraElement)
{
LinkNodePtr tempNodePtr = (LinkNodePtr)malloc(sizeof(struct LinkNode));
tempNodePtr->data = paraElement;
tempNodePtr->next = NULL;
paraQueuePtr->rear->next = tempNodePtr;
paraQueuePtr->rear = tempNodePtr;
}//off enqueue
int dequeue(LinkQueuePtr paraQueuePtr)
{
int resultValue;
LinkNodePtr tempNodePtr;
if (paraQueuePtr->front == paraQueuePtr->rear)
{
printf("the queue is empty\r\n");
return -1;
}//off if
tempNodePtr = paraQueuePtr->front->next;
resultValue = tempNodePtr->data;
paraQueuePtr->front->next = paraQueuePtr->front->next->next;
if (paraQueuePtr->rear == tempNodePtr)
{
paraQueuePtr->rear = paraQueuePtr->front;
}//off if
free(tempNodePtr);
return resultValue;
}//off dequeue
void LinkQueueTest()
{
LinkQueuePtr tempQueuePtr = initQueue();
enqueue(tempQueuePtr, 10);
enqueue(tempQueuePtr, 20);
enqueue(tempQueuePtr, 50);
outputLinkQueue(tempQueuePtr);
printf("dequeue get %d\r\n", dequeue(tempQueuePtr));
printf("dequeue get %d\r\n", dequeue(tempQueuePtr));
printf("dequeue get %d\r\n", dequeue(tempQueuePtr));
enqueue(tempQueuePtr, 8);
outputLinkQueue(tempQueuePtr);
}//off LinkQueueTest
int main()
{
LinkQueueTest();
return 0;
}
1.链队列的结构定义和初始化
typedef struct LinkNode {
int data;
struct LinkNode* next;
}*LinkNodePtr;
typedef struct LinkQueue {
LinkNodePtr front;
LinkNodePtr rear;
}*LinkQueuePtr;
LinkQueuePtr initQueue()
{
LinkQueuePtr resultPtr = (LinkQueuePtr)malloc(sizeof(struct LinkQueue));
LinkNodePtr headerPtr = (LinkNodePtr)malloc(sizeof(struct LinkNode));
headerPtr->data = 0;
headerPtr->next = NULL;
resultPtr->front = headerPtr;
resultPtr->rear = headerPtr;
return resultPtr;
}//off initQueue
这里定义了一个可以存储两个单链表节点的结构体指针LinkQueuePtr,其中front表示单链表的头指针(队头),rear表示单链表的尾指针(队尾)。在链队列的初始化中,定义了空队resultPtr和空表headerPtr,因为当前为空表,所以队头front和队尾rear都指向空表头headerPtr,返回空队resultPtr。
2.入队
void enqueue(LinkQueuePtr paraQueuePtr, int paraElement)
{
LinkNodePtr tempNodePtr = (LinkNodePtr)malloc(sizeof(struct LinkNode));
tempNodePtr->data = paraElement;
tempNodePtr->next = NULL;
paraQueuePtr->rear->next = tempNodePtr;
paraQueuePtr->rear = tempNodePtr;
}//off enqueue
入队时先新给新的队尾tempNodePtr开辟一块空间存储新的数据,让rear->next指向tempNodePtr,再让rear指向新的队尾,实现入队。因为rear初始指向表头headerPtr,移动也是在表头为headerPtr的单链表上移动,所以入队时移动rear本质上是和链表的尾插是一样的,只是表示方法不一样。
3.出队
int dequeue(LinkQueuePtr paraQueuePtr)
{
int resultValue;
LinkNodePtr tempNodePtr;
if (paraQueuePtr->front == paraQueuePtr->rear)
{
printf("the queue is empty\r\n");
return -1;
}//off if
tempNodePtr = paraQueuePtr->front->next;
resultValue = tempNodePtr->data;
paraQueuePtr->front->next = paraQueuePtr->front->next->next;
if (paraQueuePtr->rear == tempNodePtr)
{
paraQueuePtr->rear = paraQueuePtr->front;
}//off if
free(tempNodePtr);
return resultValue;
}//off dequeue
就像排队时前出后进一样,出队移出的是队列的第一个节点。出队操作中,当front和rear的地址一致时,表示这个队列是一个空队,也可以说这个表是一个空表,空队列没有存储任何数据(不包括表头headerPtr),所以返回-1。当队列不是一个空队时,用一个整形resultValue接收出队节点的数据,tempNodePtr指向出队节点。让队头front->next指向front->next->next来将出队节点移出队列,再释放tempNodePtr(出队节点)。若此时队尾rear的地址与出队节点相等,说明此节点出队后队列就是个空队,所以让队尾指向队头,完成队列的置空。