🌈队列相关概念
1.储存了数据的节点从一端(队尾)进入队列(入队尾插),从另一端(队头)出队列(出队头删),先进先出。进行插入操作的一端称为队尾,进行进行删除操作的一端称为队头。
2.用途:由于先进先出的功能,链队列可以用来历史重演,如排队叫号(先到的人先被叫到)。(栈结构由于后进先出的功能,可以用来历史的回溯,比如撤销上一秒操作的内容)
🌈链队列基础框架
🎈Queue.h定义声明
c
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int DataType;
typedef struct Node {
DataType data;
struct Node* next;
}Node;
typedef struct Queue {
Node* head;
Node* tail;
int size;
}Queue;
void InitQueue(Queue* pq);
void Destroy(Queue* pq);
void Push(Queue* pq, DataType x);
void Pop(Queue* pq);
DataType Front(Queue* pq);
void Display(Queue* pq);
🎈Queue.c函数实现
☀️初始化:InitQueue()
c
#define _CRT_SECURE_NO_WARNINGS
#include"Queue.h"
void InitQueue(Queue* pq) {
assert(pq);
pq->head = pq->tail = NULL;
pq->size = 0;
}
☀️销毁:Destroy()
c
void Destroy(Queue* pq) {
assert(pq);
if (pq->head) {
Node* cur = pq->head->next;
while (cur) {
Node* next = cur->next;
free(cur);
cur = next;
}
}
pq->head = pq->tail = NULL;
pq->size = 0;
}
☀️入队:Push()
c
void Push(Queue* pq, DataType x) {
assert(pq);
Node* newnode = (Node*)malloc(sizeof(Node));
newnode->data = x;
newnode->next = NULL;
if (!newnode) {
perror("malloc fail");
exit(-1);
}
//首次入队
if (pq->tail == NULL) {
pq->head = pq->tail = newnode;
}
//非首次入队,对头是有元素的
else {
pq->tail->next = newnode;
pq->tail = newnode;
}
pq->size++;
}
☀️出队:Pop()
c
void Pop(Queue* pq) {
assert(pq);
//当头指针与尾指针重合,说明队内只剩一个元素,该元素出队后,队列回到初始化状态(头尾指针都为空)
if (pq->head == pq->tail) {
pq->head = pq->tail = NULL;
}
else {
Node* next = pq->head->next;
free(pq->head);
pq->head = next;
}
pq->size--;
}
☀️得到队头元素:Front()
c
DataType Front(Queue* pq) {
assert(pq);
assert(pq->tail);
return pq->head->data;
}
☀️打印整个队列:Display()
c
void Display(Queue* pq) {
assert(pq);
Node* cur = pq->head;
while (cur) {
printf("%d->", cur->data);
cur = cur->next;
}
printf("NULL");
}
🎈test.c主函数,测试
c
#define _CRT_SECURE_NO_WARNINGS
#include"Queue.h"
int main() {
Queue Q;
InitQueue(&Q);
DataType data = 1;
Push(&Q, data);
data = 2;
Push(&Q, data);
data = 3;
Push(&Q, data);
data = 4;
Push(&Q, data);
Display(&Q);
printf("\n");
DataType del = Front(&Q);
Pop(&Q);
Display(&Q);
printf(" 出队元素是%d\n", del);
del = Front(&Q);
Pop(&Q);
Display(&Q);
printf(" 出队元素是%d\n", del);
del = Front(&Q);
Pop(&Q);
Display(&Q);
printf(" 出队元素是%d\n", del);
del = Front(&Q);
Pop(&Q);
Display(&Q);
printf(" 出队元素是%d\n", del);
Destroy(&Q);
}
☀️测试运行结果:
🌈用链队列形式实现学生信息的入队与出队
🎈Queue.h定义声明
c
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef struct student {
int age;
int height;
double weight;
}Student;
typedef struct Node {
Student stu;
struct Node* next;
}Node;
typedef struct Queue {
Node* head;
Node* tail;
int size;
}Queue;
void InitQueue(Queue* pq);
void Destroy(Queue* pq);
void GetVal(Student* stu);
Node* CreateNode(Student* stu);
void Push(Queue* pq, Student* stu);
void Pop(Queue* pq);
void PrintNode(Student* stu);
void Display(Queue* pq);
🎈Queue.c函数实现
c
#define _CRT_SECURE_NO_WARNINGS
#include"Queue.h"
void InitQueue(Queue* pq) {
assert(pq);
pq->head = pq->tail = NULL;
pq->size = 0;
}
void Destroy(Queue* pq) {
assert(pq);
Node* cur = pq->head;
while (cur) {
Node* next = cur->next;
free(cur);
cur = next;
}
pq->head = pq->tail = NULL;
pq->size = 0;
}
void GetVal(Student* stu) {
printf("请输入学生年龄、身高、体重:");
scanf("%d %d %lf", &stu->age, &stu->height, &stu->weight);
}
Node* CreateNode(Student* stu) {
GetVal(stu);
Node* newnode = (Node*)malloc(sizeof(Node));
if (!newnode) {
perror("malloc fail");
exit(-1);
}
newnode->stu.age = stu->age;
newnode->stu.height = stu->height;
newnode->stu.weight = stu->weight;
//newnode->stu = *stu;
newnode->next = NULL;
return newnode;
}
void Push(Queue* pq, Student* stu) {
assert(pq);
Node* newnode = CreateNode(stu);
if (pq->tail == NULL) {
pq->head = pq->tail = newnode;
}
else {
pq->tail->next = newnode;
pq->tail = newnode;
}
pq->size++;
}
void Pop(Queue* pq) {
assert(pq);
if (!pq->head)return;
else if (pq->head == pq->tail) {
pq->head = pq->tail = NULL;
pq->size = 0;
}
else{
Node* newhead = pq->head->next;
free(pq->head);
pq->head = newhead;
pq->size--;
}
}
void PrintNode(Student* stu) {
assert(stu);
printf("年龄:%-5d 身高:%-5d 体重:%-5lf", stu->age, stu->height, stu->weight);
}
void Display(Queue* pq) {
assert(pq);
Node* cur = pq->head;
if (!cur)printf("队列中无信息\n");
while (cur) {
PrintNode(&cur->stu);
printf("\n");
cur = cur->next;
}
}
🎈test.c主函数,测试
c
#define _CRT_SECURE_NO_WARNINGS
#include"Queue.h"
int main() {
Queue Q;
InitQueue(&Q);
Student stu;
Push(&Q, &stu);
Push(&Q, &stu);
Push(&Q, &stu);
Display(&Q);
Student del = Q.head->stu;
Pop(&Q);
printf("出队的一组数据是:");
PrintNode(&del);
printf("\n");
del = Q.head->stu;
Pop(&Q);
printf("出队的一组数据是:");
PrintNode(&del);
printf("\n");
del = Q.head->stu;
Pop(&Q);
printf("出队的一组数据是:");
PrintNode(&del);
printf("\n");
Destroy(&Q);
}
🎈测试运行结果:
注意:scanf的占位符只能写类似"%d %lf"等等,不能写"%-5d",否则会导致数据存储不到目的空间,并且数据与数据间用什么符号隔开,在输入数据时就要严格用同样符号隔开。只有在使用printf函数并且需要调整数据打印出的位置时才用类似"%-5d"。以下是scanf占位符书写有误时的运行结果: