上篇博文:(【 C 】队列 简记)简单的讲了一下队列,对队列的基本知识有了一个简单的了解,这篇博文承接上篇博文,主讲如何通过链式结构来实现队列。
如上图,提出了一个问题,队列的插入和删除操作分别在链表的两头进行,那么front和rear应该哪一个在链表的起始位置,哪一个在链表的末尾?
这就要看单链表的删除可以在哪一段操作了,我们都知道单链表的插入在哪里都能够进行,但删除操作呢?
单链表的插入操作相关知识见博文:【 C 】在单链表中插入一个新节点的尝试(一)
视频上说,在单链表的起始位置可以进行插入和删除的操作,但是在单链表的尾部呢?如果做删除操作,则找不到上一个节点了。因此,只能Front在链表的起始位置,而Rear在链表的尾部。
知道了这些,我们就可以给出两个结构,一个结构定义链表的节点,一个结构定义队列的两个指针,如下:
给出出队操作示例:
可复制版:
ElementType DeleteQ ( LinkQueue *PtrQ )
{
Qnode *FrontCell;
ElementType FrontElem;
if ( PtrQ->front == NULL)
{
printf(“ 队列空”);
return ERROR;
}
FrontCell = PtrQ->front;
if ( PtrQ->front == PtrQ->rear) /* 若队列只有一个元素 */
PtrQ->front = PtrQ->rear = NULL; /* 删除后队列置为空 */
else
PtrQ->front = PtrQ->front->Next;
FrontElem = FrontCell->Data;
free( FrontCell ); /* 释放被删除结点空间 */
return FrontElem;
}
简单解释下上面的程序,这种传统的出队操作,删除队列尾部的一个值,然后返回该值。
这个出队函数的形参是一个指向队列结构LinkQueue的指针,该指针有两个元素,分别为front指针和rear指针,这两个指针分别指向队列的头和尾部节点。
函数内部定义一个指向队列节点结构Qnode的指针,这个结构的内部有两个元素,一个是用于指向下一个节点的指针字段和一个值(存储队列元素的值)。
FrontElem被定义为一个队列类型的变量。
首先判断队列是否为空,如果队列为空,则指向队列节点的指针为空。对应程序如下:
如果不为空,则找到队列的头一个节点,对应的程序如下:
接下来判别队列中是否只有一个元素,如果队列中只有一个元素,则删除头节点之后,队列置空,对应语句如下:
否则,队列中还有其他元素,队列的front指针指向下一个节点,同时返回原本第一个节点的元素,释放删除节点的内存空间,并返回队头节点元素值。对应语句:
上面是传统的出队操作。
下面根据自己的理解写一个入队操作的函数:
void AddQ( LinkQueue *PtrQ, ElementType RearElem ) //RearElem为传入新节点的值
{
Qnode *RearNode;
RearNode = ( QNode* )malloc( sizeof( QNode ) );
assert( RearNode != NULL );//内存分配成功,继续运行,否则退出程序
PtrQ->rear->Next = RearNode; //原本队列尾部节点指针指向新插入节点
RearNode->Next = NULL; //新节点指针字段为NULL,因为它成为了尾节点
RearNode->Data = RearElem; //为新插入节点赋值
PtrQ->rear = RearNode; //rear指针指向新节点,也就是队列尾部
}