队列的概念及结构:
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出的规则FIFO(First In First Out)。
入队列:进行插入操作的一端称为队尾。
出队列:进行删除操作的一端称为队头。
队列的作用:
队列主要是运用于任务调度和消息传递等一些场景当中,在很多地方都会有队列的身影,所有学习队列是有必要的。
源码:
好了,废话不多说,直接上源码!!!
.h文件,主要是创建了一些学生信息和列表以及结点相关结构体。
#define _CRT_SECURE_NO_WARNINGS
#pragma once
#ifndef _STU_H
#define _STU_H
typedef struct
{
int num;
char name[10];
}Student;
//队列结构体
/*
StuQListNode---------结构体标签
Stu_Node-------------结构体类型
*/
typedef struct StuQListNode
{
struct StuQListNode* next;//指向下一个节点指针
Student data;//节点数据
}Stu_Node;
typedef struct
{
Stu_Node* front;//头指针
Stu_Node* rear;//尾指针
}Stu_Queue;
void Stu_Queue_Init(Stu_Queue* q);
void Queue_Pop_Add(Stu_Queue* q, int stu_num, const char* stu_name);
void Queue_Push_Add(Stu_Queue* q, int stu_num, const char* stu_name);
void Queue_Stu_Del(Stu_Queue* q, int stu_num);
void Queue_Stu_Updata(Stu_Queue* q, int stu_num, int new_num, const char* new_name);
void Queue_Stu_find(Stu_Queue* q, int stu_num);
void find_all(Stu_Queue* q);
void Queue_roll(Stu_Queue* q);
void adjacent_node(Stu_Queue* q, int stu_num1, int stu_num2);
int Queue_sum(Stu_Queue* q);
#endif // !_STU_H
.c文件,主要是实现了一些学生信息队列的基本操作,包括增删改查,结点翻转,相邻结点交换位置,计算队列结点数量的一些操作。
#include "main.h"
//创建节点
Stu_Node* Create_Node(int stu_num, const char* stu_name)
{
Stu_Node* node = (Stu_Node*)malloc(sizeof(Stu_Node));
if (node != NULL)
{
node->data.num = stu_num;
strncpy(node->data.name, stu_name, sizeof(node->data.name) - 1);
node->data.name[sizeof(node->data.name) - 1] = '\0'; // 确保字符串以 null 结尾
node->next = NULL;
}
return node;
}
//初始化队列
void Stu_Queue_Init(Stu_Queue* q)
{
q->front = NULL;
q->rear = NULL;
}
//头部增加数据
void Queue_Pop_Add(Stu_Queue* q, int stu_num, const char* stu_name)
{
Stu_Node* node = Create_Node(stu_num, stu_name);
if (q->front == NULL)
{
q->front = q->rear = node;
}
else
{
node->next = q->front;
q->front = node;
}
}
//尾部增加数据
void Queue_Push_Add(Stu_Queue* q, int stu_num, const char* stu_name)
{
Stu_Node* node = Create_Node(stu_num, stu_name);
if (q->front == NULL)
{
q->front = q->rear = node;
}
else
{
q->rear->next = node;
q->rear = node;
}
}
//删除节点
void Queue_Stu_Del(Stu_Queue* q, int stu_num)
{
Stu_Node* node = q->front;
Stu_Node* node_data = NULL;
// 查找包含指定学号的节点
while (node != NULL && node->data.num != stu_num)
{
node_data = node;
node = node->next;
}
if (node != NULL)
{
// 检查是否是头节点或尾节点
if (node_data != NULL)
{
node_data->next = node->next;
}
else q->front = node->next;
if (node == q->rear) q->rear = node_data;
free(node);
}
else printf("Not found\n");
}
//修改节点数据
void Queue_Stu_Updata(Stu_Queue* q,int stu_num,int new_num,const char* new_name)
{
Stu_Node* node = q->front;
while (node != NULL && node->data.num != stu_num)
{
node = node->next;
}
if (node != NULL)
{
node->data.num = new_num;
strcpy(node->data.name, new_name);
}
else printf("not found\n");
}
//查找某个节点数据
void Queue_Stu_find(Stu_Queue* q, int stu_num)
{
Stu_Node* node = q->front;
while (node != NULL && node->data.num != stu_num)
{
node = node->next;
}
if (node != NULL)
{
printf("ID:%d NAME:%s\n", node->data.num, node->data.name);
}
else printf("not found\n");
}
//打印所有节点
void find_all(Stu_Queue* q)
{
if (q->front==NULL)
{
printf("No data\n");
return;
}
Stu_Node* node = q->front;
while (node != NULL)
{
printf("ID:%d NAME:%s\n", node->data.num, node->data.name);
node = node->next;
}
}
//队列翻转
void Queue_roll(Stu_Queue* q)
{
Stu_Node* stack = NULL; //创建一个指向`Stu_Node结构体的指针,用于构建一个栈,该栈将帮助我们翻转队列中的元素。
Stu_Node* current = q->front; //创建一个指向当前队列头部的指针。
//当队列不为空时执行以下循环-----入栈
while (current != NULL)
{
Stu_Node* next = current->next; //保存当前节点的下一个节点。
current->next = stack; //将当前节点的`next`指针指向栈的顶部,实现入栈操作。
stack = current; //将栈的顶部指针指向当前节点,更新栈的顶部。
current = next; //移动到下一个节点。
}
q->front = stack; //更新队列的头指针为栈的顶部,即反转后的队列的头。
q->rear = q->front; //更新队列的尾指针为队列的头指针,因为栈是从头到尾反转的。
//当栈不为空时执行以下循环-----出栈
while (stack != NULL)
{
if (stack->next == NULL) //如果栈的下一个节点为空,即栈的底部。
{
q->rear = stack; //更新队列的尾指针为栈的底部,即反转后的队列的尾。
}
stack = stack->next; //移动到栈的下一个节点。
}
}
//相邻两个节点交换数据
void adjacent_node(Stu_Queue* q, int stu_num1, int stu_num2)
{
Stu_Node* node1 = q->front;
Stu_Node* node2 = q->front;
Stu_Node* per1 = NULL;
Stu_Node* per2 = NULL;
while (node1 != NULL && node1->data.num != stu_num1)
{
per1 = node1;
node1 = node1->next;
}
while (node2 != NULL && node2->data.num != stu_num2)
{
per2 = node2;
node2 = node2->next;
}
if (node1 != NULL && node2 != NULL)
{
//判断是否是相邻的位置
if (node1->next == node2)//node1在前
{
Stu_Node* node = node2->next;
//判断是否处于头结点
if (per1 != NULL) per1->next = node2;
else q->front = node2;
node2->next = node1;
node1->next = node;
}
else if (node2->next == node1)//node2在后
{
Stu_Node* node = node1->next;
//判断是否处于头结点
if (per2 != NULL) per2->next = node1;
else q->front = node1;
node1->next = node2;
node2->next = node;
}
else printf("两个数据不是相邻数据\n");
}
else printf("not found\n");
}
//计算队列中结点个数
int Queue_sum(Stu_Queue* q)
{
Stu_Node* node = q->front;
int count = 0;
while (node != NULL)
{
count++;
if (node == q->rear) break;
node = node->next;
}
return count;
}
在看看mian.c里面测试的函数把!!!
#include "main.h"
int main()
{
Stu_Queue q;
Stu_Queue_Init(&q);
Queue_Push_Add(&q, 407, "张三");
Queue_Push_Add(&q, 408, "李四");
Queue_Push_Add(&q, 409, "王五");
Queue_Push_Add(&q, 410, "李二");
Queue_Push_Add(&q, 411, "麻子");
//删除某个结点
/*Queue_Stu_Del(&q, 410);*/
//修改某个结点
/*Queue_Stu_Updata(&q, 409, 412, "谢有源");*/
//寻找某个结点
/*Queue_Stu_find(&q, 409);*/
//将整个队列进行倒序
/*Queue_roll(&q);*/
//交换相邻位置的结点
/*adjacent_node(&q, 411, 410);*/
//查询队列结点数
/*printf("num=%d\n", Queue_sum(&q));*/
//打印队列全部成员
find_all(&q);
return 0;
}
再看看测试结果,也是成功的创建了学生列表和插入。
为了防止部分初学者找不到一些函数的头文件,我在这里把mian.h里面的头文件也提供出来把!
#define _CRT_SECURE_NO_WARNINGS //用于strncpy函数
#pragma once
#ifndef _MAIN_H
#define _MAIN_H
//库头文件
#include <stdio.h>
#include "malloc.h"
#include "string.h"
//.c头文件
#include "test.h"
#include "stu.h"
#endif // !_MAIN_H
好了,以前就是学生列表的一些基本操作,仅供参考学习,大家也可以根据学生信息的不同,修改学生信息结构的内容,在此祝大家一帆风顺!!!