上篇我们提到了队列的基本概念与操作,这篇我们利用链表的方式来实现队列。
要用到链表,我们发现无论是头插头删还是尾插尾删都会涉及到遍历链表,所以这是不可避免的。再者,再对链表进行头部尾部处理的时候,我们应该引入一个新的指针,一个指针指向链表的头部,另一个指向尾部,这样我们就可以轻松的进行入队与出队。
实现
//linkqueue.h
#pragma once
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
typedef char LinkQueueType;
typedef struct LinkQueueNode{
LinkQueueType data;
struct LinkQueueNode* next;
}LinkQueueNode;//链表内的元素节点
typedef struct LinkQueue{
LinkQueueNode* head;
LinkQueueNode* tail;
}LinkQueue;//这里的两个指针分别是链表的头部与尾部,在初始化的时候创建一个伪节点当做队首,我们不考虑这个伪节点的data的内容
void LinkQueueInit(LinkQueue* q);//初始化链式队列
void LinkQueuePush(LinkQueue* q, LinkQueueType value);//入队
void LinkQueuePop(LinkQueue* q);//出队
void DestroyLinkQueue(LinkQueue* q);//销毁队列
int LinkQueueGetFront(LinkQueue* q, LinkQueueType* value);//获取队首
//linksqueue.c
#include "linkqueue.h"
#define HEAD printf("=================%s================\n",__FUNCTION__)
void LinkQueueInit(LinkQueue* q)//初始化链式队列
{
if(q == NULL)
{
return;
}
q->head = q->tail = (LinkQueueNode*)malloc(sizeof(LinkQueueNode));//这里就是创建伪节点
if(q -> head == NULL)
{
return;
}
q->head->next = NULL;
}
void LinkQueuePush(LinkQueue* q, LinkQueueType value)//入队
{
if(q == NULL)
{
return;
}
if(q->head == NULL)
{
return;
}
LinkQueueNode* cur = q->head;
LinkQueueNode* new_node = (LinkQueueNode*)malloc(sizeof(LinkQueueNode));
new_node->data = value;
new_node->next = NULL;
while(cur->next != NULL)
{
cur = cur->next;
}
cur->next = new_node;
q->tail = new_node;
return;
}
void LinkQueuePop(LinkQueue* q)//出队
{
if(q == NULL)
{
return;
}
if(q->head == NULL || q->head->next == NULL)
{
return;
}
LinkQueueNode* cur = q->head;
LinkQueueNode* to_delete = cur->next;
cur->next = to_delete->next;
free(to_delete);
to_delete = NULL;
return;
}
void DestroyLinkQueue(LinkQueue* q)//销毁队列
{
if(q == NULL)
{
return;
}
if(q->head == NULL)
{
return;
}
while(q->head != NULL)
{
q->tail = q->head->next;
free(q->head);
q->head = q->tail;
}
return;
}
int LinkQueueGetFront(LinkQueue* q, LinkQueueType* value)//获取队首
{
if(q == NULL)
{
return -1;
}
if(q->head == NULL || q->head->next == NULL)
{
return -1;
}
*value = q->head->next->data;
return 1;
}
//测试函数如下
void LinkQueuePrint(LinkQueue* q)//打印链表的内容来校验是否成功入队出队等
{
if(q == NULL)
{
return;
}
if(q->head->next == NULL)
{
return;
}
LinkQueueNode* cur = q->head->next;//这里我们不关注伪节点下的data内容,所以打印从next开始打印
while(cur != NULL)
{
printf("%c ",cur->data);
cur = cur->next;
}
printf("\n");
}
void TestPush()
{
HEAD;
LinkQueue q;
LinkQueueInit(&q);
LinkQueuePush(&q,'a');
LinkQueuePrint(&q);
LinkQueuePush(&q,'b');
LinkQueuePrint(&q);
LinkQueuePush(&q,'c');
LinkQueuePrint(&q);
LinkQueuePush(&q,'d');
LinkQueuePrint(&q);
}
void TestPop()
{
HEAD;
LinkQueue q;
LinkQueueInit(&q);
LinkQueuePush(&q,'a');
LinkQueuePush(&q,'b');
LinkQueuePush(&q,'c');
LinkQueuePush(&q,'d');
LinkQueuePrint(&q);
LinkQueuePop(&q);
LinkQueuePrint(&q);
}
void TestGetFront()
{
HEAD;
LinkQueue q;
LinkQueueType value;
LinkQueueInit(&q);
int ret = LinkQueueGetFront(&q,&value);
printf("expected ret -1, actual ret %d\n",ret);
LinkQueuePush(&q,'a');
LinkQueuePush(&q,'b');
LinkQueuePush(&q,'c');
LinkQueuePush(&q,'d');
LinkQueuePrint(&q);
ret = LinkQueueGetFront(&q,&value);
printf("expected ret 1, actual ret %d\n",ret);
printf("expected value a, actual value %c\n",value);
}
int main()
{
TestPush();
TestPop();
TestGetFront();
printf("\n");
printf("\n");
printf("\n");
printf("\n");
return 0;
}
欢迎大家共同讨论,如有错误及时联系作者指出,并改正。谢谢大家!