大家好!这篇我们继续讲解数据结构里的队列。
队列的概念
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出的原则。
入队列:进行插入操作的一端称为队尾。
出队列:进行删除操作的一端称为队头。
队列的实现
队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。
队列的结构
在单链表中,我们只定义了一个头指针,没有定义尾指针。因为定义尾指针,能方便尾插,但不能方便其它问题,所以我们没有必要。
但是队列只在队尾插入,所以这里我们可以定义一个尾指针。
所以,当我们定义多个变量时,我们需要一个结构体。
所以,队列的结构如下:
typedef int QDataType;
typedef struct QueueNode
{
struct QueueNode* next;
QDataType data;
}QueueNode;
typedef struct Queue
{
QueueNode* head;
QueueNode* tail;
}Queue;
初始化
我们要改变结构体里的内容,所以我们可以传一个结构体指针(一级指针)。
void QueueInit(Queue* pq)
{
assert(pq);
pq->head = NULL;
pq->tail = NULL;
}
销毁
销毁非常的简单,直接看代码:
void QueueDestroy(Queue* pq)
{
assert(pq);
QueueNode* cur = pq->head;
while (cur)
{
//保存下一个节点的地址
QueueNode* next = cur->next;
free(cur);
cur = next;
}
pq->head = pq->tail = NULL;
}
判断队列是否为空
这个非常简单,我们直接看代码:
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->tail == NULL;
}
插入函数
插入我们要分为两种情况:
1.没有节点
2.有节点
void QueuePush(Queue* pq,QDataType x)
{
assert(pq);
//创建一个节点
QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
if (newnode == NULL)
{
printf("malloc is fall\n");
exit(-1);
}
else
{
newnode->data = x;
newnode->next = NULL;
}
if (pq->head == NULL)
{
pq->head = pq->tail = newnode;
}
else
{
pq->tail->next = newnode;
pq->tail = newnode;
}
}
删除函数
队列的删除是有规定的,只能在队头删除。所以我们要更新头指针。
代码如下:
void QueuePop(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
//记录下一个节点
QDataType* next = pq->head->next;
free(pq->head);
pq->head = next;
}
但是这里,我们有一个错误。
我们删除了4个,程序应该会给我们断言,但是没有,程序挂了,这是为什么?因为我们删除了最后一个,tail变成了一个野指针。
而此时head为NULL了,所以我们应该加一个判断。
void QueuePop(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
QDataType* next = pq->head->next;
free(pq->head);
pq->head = next;
if (pq->head == NULL)
{
pq->tail = NULL;
}
}
取对头和队尾
这里很简单,我们直接看代码:
取队头数据:
QDataType QueueFront(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->head->data;
}
取队尾数据:
QDataType QueueBack(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->tail->data;
}
队列中有多少数据
这个也简单,我们遍历一遍就行了。
int QueueSize(Queue* pq)
{
assert(pq);
int n = 0;
QueueNode* cur = pq->head;
while (cur)
{
n++;
cur = cur->next;
}
return n;
}
好了,到这里,我们的队列就实现完成了,后面我还会说一些其它内容。如果大家觉得有帮助,希望可以点个赞支持一下,谢谢大家。