队列:先进先出
链式队列:
通过单链表实现队列的功能,
入队列的方式为单链表的尾插
出队列的方式为单链表的头删
链式队列的结构
//定义链式队列的节点
typedef char Datatype;
typedef struct LinkQueueNode
{
Datatype data;
struct LinkQueueNode* next;
} LinkQueueNode;
队列出队,入队要从两端操作,为了方便操作,维护两个指针来共同表示链式队列。
//定义链式队列
typedef struct LinkQueue
{
LinkQueueNode* head; //指向队头
LinkQueueNode* tail; //指向队尾
}LinkQueue;
队列的初始化
初始时队列没有元素头尾指针置空
void queueInit(LinkQueue* queue)
{
if (queue == NULL)
{
//非法
return;
}
queue->head = NULL;
queue->tail = NULL;
return;
}
链式队列入队列操作
入队列 (尾插)
(1)首先要创建一个新节点
(2)如果原队列为空,则使队头指针和队尾指针均指向新结点即可
(3)如果原队列不为空,则使队尾指针的next域指向新节点,然后队尾指针后移。
//入队列(链表尾插)
void queueInsert(LinkQueue* queue, Datatype value)
{
if (queue == NULL)
{
//非法
return;
}
LinkQueueNode* new = nodeCreate(value);
//如果队列为空
if (queue->head == NULL)
{
queue->head = queue->tail = new;
}
else //队列不为空
{
LinkQueueNode* cur = queue->tail->next;
cur = new;
queue->tail = cur;
nodeDestroy(cur); //销毁节点
}
return;
}
链式队列的出队列操作
出队列 (头删)
(1)首先要考虑队列是否为空,为空则出队失败
(2)不为空,先使队头指针指向队头结点的下一个节点作为新的队首结点,然后释放原队首节点即可。
//出队列(链表头删)
void queuePop(LinkQueue* queue)
{
if (queue == NULL)
{
//非法输入
return;
}
if (queue->head == NULL)
{
//空链表
return;
}
//头删除
LinkQueueNode* delete = queue->head;
queue->head = delete->next;
nodeDestroy(delete);
return;
}
取链式队列的首元素
(1)如果队列为空,则操作失败
(2)不为空,只需将队头指针所指向的结点数据域保存下来即可。
//成功返回0 失败返回-1
int queueFront(LinkQueue *queue, Datatype *value)
{
if (value == NULL)
{
return -1;
}
if (queue->head == NULL)
{
return -1;
}
*value = queue->head->data;
return 0;
}
链式队列的销毁操作
队列在初始化前只有两个指针,所以销毁后也要恢复到初始化前的状态。
(1)遍历链表将各节点依次销毁
(2)使队首,队尾指针置空,以防变为野指针
//销毁队列
void queueDestroy(LinkQueue* queue)
{
if (queue == NULL)
{
//feifashuru
return;
}
//从头部开始遍历队列
LinkQueueNode* cur = queue->head;
while (cur != NULL)
{
//保存要销毁的下一个节点
LinkQueueNode* later_node = cur->next;
free(cur);//销毁节点
cur = later_node;
}
//队首队尾指针置空
queue->head = NULL;
queue->tail = NULL;
return;
}
实现链式队列基本功能的其他函数
1创建节点
LinkQueueNode* nodeCreate(Datatype value)
{
LinkQueueNode* new =(LinkQueueNode*)malloc(sizeof(LinkQueueNode));
new->next = NULL;
new->data = value;
return new;
}
2销毁节点
void nodeDestroy(LinkQueueNode* delete)
{
free(delete);
delete->data = 0;
delete->next = NULL;
}