目录
前言
1.什么是链队
2.链队的表示和实现
1.定义
2.初始化
3.销毁
4.清空
5.空队列
6.队列长度
7.获取队头
8.入队
9.出队
10.遍历队列
11.完整代码
前言
本篇博客介绍链栈队列的表示和实现。
1.什么是链队
链队是采用链式存储结构实现的队列。通常链队使用单链表表示。
图1.链队的示意图
为了操作方便,我们给链队列增加一个头结点,令头指针始终指向头结点。
2.链队的表示和实现
1.定义
typedef int QElemType;
typedef int Status;
typedef struct QNode{QElemType data;struct QNode * next;
}QNode,*QueuePtr;
typedef struct {QueuePtr front;//队头指针QueuePtr rear;//队尾指针
}LinkQueue;
2.初始化
初始化的时候给链队分配一个结点。
图2.空队列
//初始化
Status initLinkQueue(LinkQueue * linkQueue){linkQueue->front = linkQueue->rear = (QueuePtr)malloc(sizeof(QNode));if (!linkQueue->front) {return 0;}return 1;
}
3.销毁
当需要销毁队列时,我们需要释放队列中所有节点的内存,并将队列结构体中的指针置空。
我们需要遍历所有的结点,释放结点内存,最后置空头结点。
// 销毁队列
void destroyLinkQueue(LinkQueue *linkQueue) {while (linkQueue->front) { // 循环释放队列中所有节点的内存QueuePtr temp = linkQueue->front;linkQueue->front = linkQueue->front->next;free(temp);}linkQueue->rear = NULL; // 将 rear 指针置空
}
4.清空
清空队列的方法与销毁队列的方法类似,但不释放队列结构体本身的内存,只释放队列中节点的内存并将队列恢复到初始状态。
// 清空队列
void clearLinkQueue(LinkQueue *linkQueue) {while (linkQueue->front) { // 循环释放队列中所有节点的内存QueuePtr temp = linkQueue->front;linkQueue->front = linkQueue->front->next;free(temp);}linkQueue->rear = NULL; // 将 rear 指针置空
}
5.空队列
队头和队尾相同的时候为空队列。
// 判断队列是否为空
Status isLinkQueueEmpty(LinkQueue *linkQueue) {return linkQueue->front == NULL; // 如果队头指针为空,则队列为空
}
6.队列长度
// 计算队列长度
int getLinkQueueLength(LinkQueue *linkQueue) {int length = 0;QueuePtr p = linkQueue->front->next; // 从队头指针开始while (p != NULL) { // 遍历队列length++;p = p->next;}return length;
}
7.获取队头
获取队头元素。
// 获取队列头结点
Status getLinkQueueFront(LinkQueue *linkQueue, QElemType *element) {if (linkQueue->front == NULL) { // 队列为空return 0;}*element = linkQueue->front->next->data; // 将队头节点的数据存储到 element 中return 1;
}
8.入队
入队列的时候如下所示。
图3.入队列示意图
// 入队列
Status enLinkQueue(LinkQueue * linkQueue,QElemType element){QueuePtr newNode = (QNode *)malloc(sizeof(QNode));//生成一个新节点if (!newNode) {return 0;}newNode->data = element;newNode->next = NULL;linkQueue->rear->next = newNode;linkQueue->rear = newNode;return 1;
}
9.出队
出队列的时候如下如所示:
图4.出队列示意图
// 出队列
Status deLinkQueue(LinkQueue * linkQueue,QElemType *element){if (linkQueue->front == linkQueue->rear) {//空队列return 0;}QueuePtr p = linkQueue->front->next;// 指向头结点* element = p->data;linkQueue->front->next = p->next;//修改头指针if (linkQueue->front == p) {//如果仅有一个节点linkQueue->rear = linkQueue->front;//修改尾指针}free(p);return 1;
}
10.遍历队列
// 遍历队列(忽略头结点)
void traverseLinkQueueIgnoreHead(LinkQueue *linkQueue) {if (linkQueue->front == NULL || linkQueue->front->next == NULL) { // 队列为空或只有头结点printf("队列为空\n");return;}QueuePtr current = linkQueue->front->next; // 从头结点的下一个节点开始遍历while (current != NULL) { // 遍历直到队尾printf("%d\t", current->data); // 打印当前节点的数据current = current->next; // 移动到下一个节点}printf("\n");
}
11.完整代码
#include <stdlib.h>typedef int QElemType;
typedef int Status;
typedef struct QNode{QElemType data;struct QNode * next;
}QNode,*QueuePtr;
typedef struct {QueuePtr front;//队头指针QueuePtr rear;//队尾指针
}LinkQueue;//初始化
Status initLinkQueue(LinkQueue * linkQueue){linkQueue->front = linkQueue->rear = (QueuePtr)malloc(sizeof(QNode));if (!linkQueue->front) {return 0;}return 1;
}
// 销毁队列
void destroyLinkQueue(LinkQueue *linkQueue) {while (linkQueue->front) { // 循环释放队列中所有节点的内存QueuePtr temp = linkQueue->front;linkQueue->front = linkQueue->front->next;free(temp);}linkQueue->rear = NULL; // 将 rear 指针置空
}
// 清空队列
void clearLinkQueue(LinkQueue *linkQueue) {while (linkQueue->front) { // 循环释放队列中所有节点的内存QueuePtr temp = linkQueue->front;linkQueue->front = linkQueue->front->next;free(temp);}linkQueue->rear = NULL; // 将 rear 指针置空
}
// 判断队列是否为空
Status isLinkQueueEmpty(LinkQueue *linkQueue) {return linkQueue->front == NULL; // 如果队头指针为空,则队列为空
}
// 计算队列长度
int getLinkQueueLength(LinkQueue *linkQueue) {int length = 0;QueuePtr p = linkQueue->front->next; // 从队头指针开始while (p != NULL) { // 遍历队列length++;p = p->next;}return length;
}
// 获取队列头结点
Status getLinkQueueFront(LinkQueue *linkQueue, QElemType *element) {if (linkQueue->front == NULL) { // 队列为空return 0;}*element = linkQueue->front->next->data; // 将队头节点的数据存储到 element 中return 1;
}
// 遍历队列
// 遍历队列(忽略头结点)
void traverseLinkQueueIgnoreHead(LinkQueue *linkQueue) {if (linkQueue->front == NULL || linkQueue->front->next == NULL) { // 队列为空或只有头结点printf("队列为空\n");return;}QueuePtr current = linkQueue->front->next; // 从头结点的下一个节点开始遍历while (current != NULL) { // 遍历直到队尾printf("%d\t", current->data); // 打印当前节点的数据current = current->next; // 移动到下一个节点}printf("\n");
}// 入队列
Status enLinkQueue(LinkQueue * linkQueue,QElemType element){QueuePtr newNode = (QNode *)malloc(sizeof(QNode));//生成一个新节点if (!newNode) {return 0;}newNode->data = element;newNode->next = NULL;linkQueue->rear->next = newNode;linkQueue->rear = newNode;return 1;
}
// 出队列
Status deLinkQueue(LinkQueue * linkQueue,QElemType *element){if (linkQueue->front == linkQueue->rear) {//空队列return 0;}QueuePtr p = linkQueue->front->next;// 指向头结点* element = p->data;linkQueue->front->next = p->next;//修改头指针if (linkQueue->front == p) {//如果仅有一个节点linkQueue->rear = linkQueue->front;//修改尾指针}free(p);return 1;
}void testLinkQueue(void){LinkQueue queue;if (initLinkQueue(&queue)) {printf("链队列初始化成功!\n");}else {printf("链队列初始化失败!\n");}if (isLinkQueueEmpty(&queue)) {printf("队列为空\n");}printf("队列长度:%d\n",getLinkQueueLength(&queue));for (int i = 1; i <= 10 ; i++) {if (enLinkQueue(&queue, i)) {printf("数据元素%d入队成功!\n",i);}else{printf("入队失败!\n");}}printf("遍历链队列初!\n");if (!isLinkQueueEmpty(&queue)) {printf("队列不为空\n");}QElemType headFront;if (getLinkQueueFront(&queue, &headFront)) {printf("队列头结点获取成功,队头元素为:%d\n",headFront);}traverseLinkQueueIgnoreHead(&queue);printf("队列长度:%d\n",getLinkQueueLength(&queue));printf("队列长度:%d\n",getLinkQueueLength(&queue));for (int i = 1; i <= 10 ; i++) {int element;if (deLinkQueue(&queue, &element)) {printf("出队列成功,出队列的数据元为素%d!\n",element);}else{printf("入队失败!\n");}}destroyLinkQueue(&queue);
}