上一期中,我们学习了栈,今天我们来学习一种新的结构叫队列
与栈不同的是,它的数据是先进先出,根据这种结构的特征我们选择使用链表来完成,因为我们只需要实现尾部插入和头部删除的部分就可以了
队列的结构中和单链表的结构类似,包含下一个结点的指针,同时我们还需要定义一个尾指针,来记录尾部的位置
这个是结点的结构体:
于此之外,我们还需要创建一个新的结构体来管理整个队列:里面存储的是头部结点和尾部结点
所以以下是实现队列的关键函数:
下面是队列的初始化函数:
入队函数:
出队函数:
对于队列中我们要实现判断它是否为空的函数:
队列中我们还要实现取出队头函数和取出队尾元素,同时我们还要计算队列中的元素
以上就是关于队列的内容,希望对大家有所帮助!!!
下面是完整的代码
void QInit(queue* qp)//初始化队列
{
assert(qp);
qp->phead = qp->phead = NULL;
qp->size = 0;
}
void QPush(queue* qp, Datatype x)//入队
{
assert(qp);
qnode* newnode = (qnode*)malloc(sizeof(qnode));
if (newnode == NULL)
{
perror("malloc_fail");
return;
}
newnode->data = x;
newnode->next = NULL;
if (qp->phead == NULL)
{
qp->phead = qp->ptail = newnode ;
}//为空的情况下
else
{
qp->ptail->next = newnode;
qp->ptail = newnode;
}//尾部插入
qp->size++;
}
bool QEmpty(queue* qp)
{
assert(qp);
return qp->size == 0;
}
void QPop(queue* qp)//出队
{
assert(qp);
assert(!QEmpty(qp));
if (qp->phead->next == NULL)
{
free(qp->phead);
qp->phead = qp->ptail = NULL;//这是删到只剩下一个结点的情况
}
else
{
queue* next = qp->phead->next;
free(qp->phead);
qp->phead = next;//这里是多个结点的情况不这样就会造成ptail的野指针问题
}
qp->size--;
}
Datatype QFront(queue* qp)//返回队首元素
{
assert(qp);
assert(!QEmpty(qp));
return qp->phead->data;
}
Datatype QBack(queue* qp)//返回队尾元素
{
assert(qp);
assert(!QEmpty(qp));
return qp->ptail->data;
}
int Qsize(queue* qp)
{
assert(qp);
return qp->size;
}
void QDestroy(queue* qp)//销毁队列
{
assert(qp);
assert(!QEmpty(qp));
qnode* cur = qp->phead;
while (cur)
{
qnode* next = cur->next;
free(cur);
cur = next;
}
qp->size = 0;
qp->phead = qp->ptail = NULL;
}