1.第一个结构是存放链表的数据,第二个结构体是存放头节点和尾节点的以方便找到尾节点,存放头节点的是phead,尾节点的是ptail
typedef struct QueueNode
{
struct QueueNode* next;//单链表
QDataType data;//放数据
}QNode;
typedef struct Queue
{
QNode* phead;//头节点
QNode* ptail;//尾节点
QDataType size; //统计有多少节点
}Queue;
2.初始化存放头节点和尾节点的第二个结构体
void QueueInit(Queue* pq)//初始化
{
assert(pq);
pq->phead = NULL;
pq->ptail = NULL;
pq->size = 0;
}
3.销毁函数,把第一个结构体节点地址存入了第二个结构体,再通过第二个结构体所存的地址去销毁第一个结构体
void QueueDestroy(Queue* pq)//销毁
{
assert(pq);
//第一个结构体
QNode* cur = pq->phead;
while (cur)
{
QNode* next = cur->next;
free(cur);
cur = next;//循环更新节点
}
pq->phead = NULL;
pq->ptail = NULL;
pq->size = 0;
}
4.插入函数,1.如果是空链表则把创建的节点的地址赋值给头指针和尾指针,2.不是空指针则把新建立的节点链接到尾指针的next上
void QueuePush(Queue* pq, QDataType x)//插入数据
{
QNode* newnode = (QNode*)malloc(sizeof(QNode));//扩大的是第一个结构体
if (newnode == NULL)
{
perror("malloc");
return;
}
newnode->data = x;
newnode->next = NULL;
if (pq->phead == NULL)
{
pq->phead = pq->ptail = newnode;
}
else
{
pq->ptail->next = newnode;
pq->ptail = newnode;
}
pq->size++;
}
5.队头出数据就是删队头。1.判空:判pq指针的空,再判pq->phead指针的空,2.如果链表只有一个节点就去了 (if语句) 删除第一个节点,3.链表有两个节点的才去(else)语句
void QueuePop(Queue* pq)//队头出数据就是删队头
{
assert(pq);
assert(!QueueEmpty(pq));//判pq->phead的空
if (pq->phead->next == NULL)
{
free(pq->phead);
pq->phead = pq->ptail = NULL;
}
else
{
QNode* next = pq->phead->next;
free(pq->phead);
pq->phead = next;
}
pq->size--;
}
6.返回对头数据,(pq指针)和(pq->phead头指针不能为空)
QDataType QueueFront(Queue* pq)//返回对头数据
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->phead->data;
}
7.返回队尾数据
QDataType QueueBack(Queue* pq)//返回队尾数据
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->ptail->data;
}
8.返回总链表节点的个数
int QueueSize(Queue* pq)//返回总的数据个数
{
assert(pq);
return pq->size;
}
9.判空函数,是空指针返回真,不是空指针返回假
bool QueueEmpty(Queue* pq)//是空的返回真
{
assert(pq);
return pq->phead == NULL && pq->ptail == NULL;
}