当前位置: 首页 > news >正文

C语言-链表_基础

链表-基础

1. 数组

1.1 静态数组

例子:int nums[5] = {0};struct person ps[5];
缺点:1,无法修改地址2,无法动态定义长度3,占用内存过大或过小4,增删速度慢
优点数组的内存是连续开辟的,所以读取速度快

1.2 动态数组

例子:int *nums = (int *) calloc(5,sizeof(int));struct person *ps = (struct person *)calloc(5,sizeof(struct person));
缺点:增删速度慢编写代码较为复杂
优点:读取效率高

2. 常用数据结构

1、数组结构:内存连续开辟

2、链表结构:离散开辟

3、树

4、二叉树(均衡二叉树,非均衡二叉树)

5、图

3. 链表结构

分类:

单链表:

  • 一个节点只记录下一个节点的地址

双链表:

  • 一个节点即记录下一个节点的地址,也记录上一个节点的地址

4. 设计节点

需求:将多个学员信息设计为链表

单链表节点设计:

typedef struct student
{//数据域char name[50];char sex[5];int num;double score;//指针域struct student *next;
}Stu;

双链表节点设计:

typedef truct student
{//数据域char name[50];char sex[5];int num;double score;//指针域struct student *next;struct student *head;
}Stu;

总结:

typedef struct 结构体名称
{//数据域//指针域
}别名;

5. 静态单链表

#include <stdio.h>
typedef struct student
{//数据域char name[50];char sex[5];int num;double score;//指针域struct student *next;
}Stu;
int main(int argc, char const *argv[])
{Stu s01 = {"张三", "男", 1, 99, NULL};Stu s02 = {"李四", "男", 2, 96, NULL};Stu s03 = {"王五", "女", 3, 97, NULL};Stu s04 = {"钱七", "男", 4, 93, NULL};Stu s05 = {"赵八", "女", 5, 97, NULL};Stu *head = &s01;   //将s01作为首节点s01.next = &s02;    //将s02设置为s01的下一个节点   s02.next = &s03;s03.next = &s04;s04.next = &s05;//链表的遍历//pd:当前链表的节点Stu *pd = head;while(pd != NULL){printf("%s %s %d %.2lf\n", pd->name, pd->sex, pd->num, pd->score);//下一个节点赋值给当前节点,为下一轮循环pd = pd->next;}return 0;
}

6. 动态单链表

动态开辟内存,存储结构体学生信息

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct student
{//数据域char name[50];char sex[5];int age;//指针域struct student *next;
}Stu;
int main(int argc, char const *argv[])
{Stu *s01 = calloc(1,sizeof(Stu));strcpy(s01->name, "陈晴朗");strcpy(s01->sex, "男");s01->age = 18;Stu *s02 = calloc(1,sizeof(Stu));strcpy(s02->name, "李槐");strcpy(s02->sex, "男");s02->age = 8;Stu *s03 = calloc(1,sizeof(Stu));strcpy(s03->name, "李宝瓶");strcpy(s03->sex, "女");s03->age = 14;Stu *s04 = calloc(1,sizeof(Stu));strcpy(s04->name, "裴钱");strcpy(s04->sex, "女");s04->age = 12;Stu *s05 = calloc(1,sizeof(Stu));strcpy(s05->name, "崔东山");strcpy(s05->sex, "男");s05->age = 16;Stu *head = s01;   //将s01作为首节点s01->next = s02;    //将s02设置为s01的下一个节点   s02->next = s03;s03->next = s04;s04->next = s05;//链表的遍历//pd:当前链表的节点Stu *pd = head;while(pd != NULL){printf("%s\t%s\t%d\n", pd->name, pd->sex, pd->age);//下一个节点赋值给当前节点,为下一轮循环pd = pd->next;}return 0;
}
// 陈晴朗  男      18
// 李槐    男      8
// 李宝瓶  女      14
// 裴钱    女      12
// 崔东山  男      16

练习:学员管理系统

需求:

选项有:1,查询所有学员信息2,添加学员信息3,插入学员信息4,删除学员信息5,修改学员信息(作业)6,查找指定位置的学员(作业)7,退出程序(释放内存)

代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct student
{//数据域char name[30];char sex[10];int num;//指针域struct student *next;
}STU;
//记录链表首节点
STU *head = NULL;//查询函数(打印链表)
void print_link(STU *head)
{//定义一个节点作为当前节点STU *pd = head;while (pd != NULL){printf("姓名:%s\t性别:%s\t学号:%d\n",pd->name,pd->sex,pd->num);//获取下一个节点赋值给当前节点pd = pd->next;}printf("\n");
}//计算链表长度
int get_len(STU *head)
{int i = 0;STU *pd = head;while(pd != NULL){i++;pd = pd->next;}return i;
}//添加学员信息逻辑
/*添加新节点到连接尾部参数;head:链表的头节点stu:要添加的新节点返回值链表的头节点
*/
STU *add(STU *head, STU *stu)
{//如果传进来的学员信息为空,直接返回传进来的头结点if (stu == NULL){return head;}//判断链表首节点是否为空,为空表示此时链表还没有节点,直接将数据赋值给首结点if (head == NULL){head = stu;printf("添加成功\n\n");return head;}//查询最后一个节点,找到NULL的前一个节点//假设当前节点就是最后一个节点(即一个也没有),此时首节点就是最后一个节点STU *lastNode = head;while(lastNode != NULL){//进循环,表示这不是最后一个节点,就判断他的下一个节点是否为空,为空直接跳出循环if (lastNode->next == NULL){break;}else{//此时表示他的下一个节点不是NULL,将它的下一个节点赋值给它lastNode = lastNode->next;}}//没有进循环表示lastNode就是当前链表的最后一个节点//此时就要将本次创建的节点添加到 原链表最后一个节点的后面lastNode->next = stu;printf("添加成功\n\n");return head;
}//尾部添加学员信息
STU *add_student(STU *head)
{//开辟一块堆内存空间赋值 结构体指针变量,用来存储学员信息(即stu指向这片堆内存)STU *stu = calloc(1,sizeof(STU));printf("请输入学员姓名\n");scanf("%s", stu->name);printf("请输入学员性别\n");scanf("%s", stu->sex);printf("请输入学员学号\n");scanf("%d", &stu->num);head = add(head, stu);return head;}//插入学员
STU *inster_student(STU *head)
{STU *stu = calloc(1,sizeof(STU));printf("请输入学员姓名\n");scanf("%s", stu->name);printf("请输入学员性别\n");scanf("%s", stu->sex);printf("请输入学员学号\n");scanf("%d", &stu->num);printf("请输入要插入学员的位置(从0开始)\n");int index = 0;scanf("%d", &index);//排除错误int len = get_len(head);if (index > len){//插入位置超过链表长度,插入链表末位head = add(head, stu);return head;}if (index < 0){printf("输入位置有误\n");return head;}//为0表示插入第一个位置if (index == 0){//将首节点位置变为下一个节点stu->next = head;//将新建的节点赋值给首节点head = stu;printf("添加成功\n");return head;}//寻找插入节点的前一个节点STU *pd = head;for (int i = 0; i < index - 1; i++){pd = pd->next;}stu->next = pd->next; //将前一个节点的原后一个节点赋值给新节点的下一个节点pd->next = stu;printf("添加成功\n\n");return head;
}//删除学员
STU *del_student(STU *head)
{printf("请输入要删除学员的位置(从0开始)\n");int index = 0;scanf("%d", &index);//排除错误int len = get_len(head);if (index > len || index < 0){printf("输入位置有误\n");return head;}//为0表示删除第一个位置if (index == 0){//将首节点的下一个节点变为首节点head = head->next;printf("删除成功\n");return head;}STU *pd1 = head, *pd2;int i = 0;while (i < index){pd2 = pd1;pd1 = pd1->next;i++;}if (pd1 != NULL){pd2->next = pd1->next;}printf("删除成功\n");return head;
}//修改学员
STU *update_student(STU *head)
{STU *stu = calloc(1,sizeof(STU));printf("请输入要修改学员姓名\n");scanf("%s", stu->name);printf("请输入要修改学员性别\n");scanf("%s", stu->sex);printf("请输入要修改学员学号\n");scanf("%d", &stu->num);printf("请输入要修改学员的位置(从0开始)\n");int index = 0;scanf("%d", &index);//排除错误int len = get_len(head);if (index > len || index < 0){printf("输入位置有误\n");return head;}//为0表示修改第一个位置if (index == 0){//将新节点的next指向原首节点的下一个节点stu->next = head->next;printf("修改成功\n");return head;}//不为0int i = 0;//定义两个指针变量记录当前节点和上一个节点STU *pd1 = head, *pd2;while (i < index){pd2 = pd1;pd1 = pd1->next;i++;}pd2->next = stu;stu->next = pd1->next;printf("修改成功\n");return head;
}//查询指定学员位置
STU *find_student(STU *head)
{printf("请输入要查找学员的位置(从0开始)\n");int index = 0;scanf("%d", &index);//排除错误int len = get_len(head);if (index > len || index < 0){printf("输入位置有误\n");return head;}STU *pd = head, *pd1;//为0表示查找的是第一个学员if (index == 0){//直接打印首节点printf("姓名:%s\t性别:%s\t学号:%d\n\n",pd->name,pd->sex,pd->num);return head;}//不为0,寻找当前节点int i = 0;while (i < index){pd1 = pd;pd = pd->next;i++;}printf("姓名:%s\t性别:%s\t学号:%d\n\n",pd->name,pd->sex,pd->num);return head;
}//菜单函数
void my_menu(int tag)
{switch (tag){case 1:print_link(head);break;case 2:head = add_student(head);break;case 3:head = inster_student(head);break;case 4:head = del_student(head);break;case 5:head = update_student(head);break;case 6:head = find_student(head);break;default:printf("输入有误, 请重新输入\n\n");break;}
}//释放内存
void free_link(STU *head)
{STU *pd = head;while (pd != NULL){//记录其下一个节点STU *next = pd->next;//释放当前节点free(pd);//更换当前节点pd = next;}}int main(int argc, char const *argv[])
{while (1){printf("1,查询所有学员信息\n2,添加学员信息\n3,插入学员信息\n4,删除学员信息\n5,修改学员信息\n6,查找指定位置的学员\n7,退出程序\n\n");printf("请输入本次操作的选项(输入对应数字)\n");int tag = 0;scanf("%d", &tag);if (tag != 7){my_menu(tag);}else{free_link(head);printf("欢迎下次光临!\n");break;}}return 0;
}

相关文章:

C语言-链表_基础

链表-基础 1. 数组 1.1 静态数组 例子:int nums[5] {0};struct person ps[5]; 缺点:1,无法修改地址2,无法动态定义长度3,占用内存过大或过小4,增删速度慢 优点数组的内存是连续开辟的,所以读取速度快1.2 动态数组 例子:int *nums (int *) calloc(5,sizeof(int));struct p…...

Java第二十一章总结

网络编程三要素 ip地址&#xff1a;计算机在网络中的唯一标识 端口&#xff1a;应用程序在计算机中唯一标识 协议&#xff1a;通信协议&#xff0c;常见有UDP和TCP协议 InetAddress类 表示Internet协议地址 //返回InetAddress对象 InetAddress byName InetAddress.…...

【keil备忘录】2. stm32 keil仿真时的时间测量功能

配置仿真器Trace内核时钟为单片机实际的内核时钟&#xff0c;需要勾选Enable设置&#xff0c;设置完成后Enable取消勾选也可以&#xff0c;经测试时钟频率配置仍然生效&#xff0c;此处设置为48MHZ: 时间测量时必须打开register窗口&#xff0c;否则可能不会计数 右下角有计…...

图的存储(邻接矩阵,边集数组,邻接表,链式前向星)

目录 &#x1f33c;图的存储 &#xff08;1&#xff09;邻接矩阵 &#xff08;2&#xff09;边集数组 &#xff08;3&#xff09;邻接表 &#xff08;4&#xff09;链式前向星 &#x1f600;刷题 &#x1f40d;最大节点 &#x1f40d;有向图 D 和 E &#x1f40d;奶牛…...

Linux 基础知识整理(二)

Linux系统目录结构 Linux采用的是树型结构。最上层是根目录&#xff0c;其他的所有目录都是从根目录出发而生成的。微软的DOS和windows也是采用树型结构&#xff0c;但是在DOS和 windows中这样的树型结构的根是磁盘分区的盘符&#xff0c;有几个分区就有几个树型结构&#xff…...

2024年值得关注的8个未来数据库

2024年值得关注的8个未来数据库 关系型数据库管理系统在数据库技术领域占据主导地位已经多年了。当SQL在1970年代首次出现时&#xff0c;关系型数据库管理系统的使用和受欢迎程度迅速提升。很快&#xff0c;MySQL成为了大多数公司和团队首选的数据库。 然而&#xff0c;2023年…...

C++新经典模板与泛型编程:将trait类模板用作模板参数

将trait类模板用作模板参数 template<typename T> struct SumFixedTraits;template<> struct SumFixedTraits<char> {using sumT int;static sumT initValue() {return 0;} };template<> struct SumFixedTraits<int> {using sumT __int64;sta…...

BUUCTF-[GYCTF2020]FlaskApp flask爆破pin

这道题不需要爆破也可以getshell ssti都给你了 {{((lipsum.__globals__.__builtins__[__import__](so[::-1])[popen]("\x63\x61\x74\x20\x2f\x74\x68\x69\x73\x5f\x69\x73\x5f\x74\x68\x65\x5f\x66\x6c\x61\x67\x2e\x74\x78\x74")).read())}} 但是学习记录一下pin…...

web前端实现LED功能、液晶显示时间、数字

MENU 效果演示html部分JavaScript部分css部分 效果演示 html部分 <div id"app"><!-- 页面 --><div class"time-box"><!-- 时 --><div class"house-box"><bit-component :num"houseTem"></bit…...

YOLOv8改进 | 2023 | DiverseBranchBlock多元分支模块(有效涨点)

一、本文介绍 本文带来的改进机制是YOLOv8模型与多元分支模块&#xff08;Diverse Branch Block&#xff09;的结合&#xff0c;Diverse Branch Block (DBB) 是一种用于增强卷积神经网络性能的结构重新参数化技术。这种技术的核心在于结合多样化的分支&#xff0c;这些分支具有…...

Spring Boot 3 整合 Spring Cache 与 Redis 缓存实战

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f33a; 仓库主页&#xff1a; Gitee &#x1f4ab; Github &#x1f4ab; GitCode &#x1f496; 欢迎点赞…...

kubeadm 安装k8s1.28.x 底层走containerd 容器

1. k8s1.28.x 的概述 1.1 k8s 1.28.x 更新 Kubernetes v1.28 是 2023 年的第二个大版本更新&#xff0c;包含了 46 项主要的更新。 而今年发布的第一个版本 v1.27 有近 60 项&#xff0c;所以可以看出来&#xff0c;在发布节奏调整后&#xff0c; 每个 Kubernetes 版本中都会包…...

“分割“安卓用户,对标iOS,鸿蒙崛起~

近期关于**“华为于明年推出不兼容安卓的鸿蒙版本”**的消息传出&#xff0c;引起了业界的热议关注。自从2019年8月&#xff0c;美国制裁下&#xff0c;华为不再能够获得谷歌安卓操作系统相关付费服务&#xff0c;如此情况下&#xff0c;华为“备胎”鸿蒙操作系统一夜转正。 华…...

【Vulnhub 靶场】【hacksudo: ProximaCentauri】【简单 - 中等】【20210608】

1、环境介绍 靶场介绍&#xff1a;https://www.vulnhub.com/entry/hacksudo-proximacentauri,709/ 靶场下载&#xff1a;https://download.vulnhub.com/hacksudo/hacksudo-ProximaCentauri.zip 靶场难度&#xff1a;简单 - 中等 发布日期&#xff1a;2021年06月08日 文件大小&…...

share pool的组成

share pool的组成 3块区域&#xff1a;free,library cache,row cache 通过查看v$librarycache视图&#xff0c;可以监控library cache的活动情况&#xff0c;进一步衡量share pool设置是否合理; 其中reloads列&#xff0c;表示对象被重新加载的次数&#xff0c;在一个设置合…...

应用案例 | 基于三维视觉的汽车零件自动化拧紧解决方案

​Part.1 引言 随着人们生活水平的提高&#xff0c;汽车作为理想的代步工具&#xff0c;逐渐成为人们生活中不可或缺的一部分。汽车的广泛应用&#xff0c;大大增加了汽车制造业的负荷。因此&#xff0c;如何提高生产效率和汽车性能&#xff0c;成为汽车制造业的首要关注话题。…...

Redis server启动源码

入口main函数 src/redis.c文件main函数 int main(int argc, char **argv) {struct timeval tv;/* We need to initialize our libraries, and the server configuration. */// 初始化库 #ifdef INIT_SETPROCTITLE_REPLACEMENTspt_init(argc, argv); #endif//设置本地时间setl…...

C++基础 强制转换

目录 static_cast&#xff1a;static_cast(expression) const_cast dynamic_cast reinterpret_cast C 提供以下几类转换 static_cast&#xff1a;static_cast<type-id>(expression) tatic_cast 主要用于以下几种情况&#xff1a; 用于显式地将一个表达式转换为另一…...

【python、opencv】opencv仿射变换原理及代码实现

opencv仿射变换原理 仿射变换是opencv的基本知识点&#xff0c;主要目的是将原始图片经过仿射变换矩阵&#xff0c;平移、缩放、旋转成目标图像。用数学公式表示就是坐标转换。 其中x&#xff0c;y是原始图像坐标&#xff0c;u&#xff0c;v是变换后的图像坐标。将公式转换为…...

mac本地部署stable-diffusion

下载Homebrew /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)" ①输入“1”选择中科大版本&#xff0c;然后输入Y(YES)&#xff0c;直接输入开机密码&#xff08;不显示&#xff09;然后回车确认&#xff0c;开始下载 ②…...

如何理解 IP 数据报中的 TTL?

目录 前言理解 前言 面试灵魂一问&#xff1a;说说对 IP 数据报中 TTL 的理解&#xff1f;我们都知道&#xff0c;IP 数据报由首部和数据两部分组成&#xff0c;首部又分为两部分&#xff1a;固定部分和可变部分&#xff0c;共占 20 字节&#xff0c;而即将讨论的 TTL 就位于首…...

#Uniapp篇:chrome调试unapp适配

chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器&#xff1a;Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...

Yolov8 目标检测蒸馏学习记录

yolov8系列模型蒸馏基本流程&#xff0c;代码下载&#xff1a;这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中&#xff0c;**知识蒸馏&#xff08;Knowledge Distillation&#xff09;**被广泛应用&#xff0c;作为提升模型…...

【分享】推荐一些办公小工具

1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由&#xff1a;大部分的转换软件需要收费&#xff0c;要么功能不齐全&#xff0c;而开会员又用不了几次浪费钱&#xff0c;借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

MFC 抛体运动模拟:常见问题解决与界面美化

在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...

C语言中提供的第三方库之哈希表实现

一. 简介 前面一篇文章简单学习了C语言中第三方库&#xff08;uthash库&#xff09;提供对哈希表的操作&#xff0c;文章如下&#xff1a; C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...

HTML前端开发:JavaScript 获取元素方法详解

作为前端开发者&#xff0c;高效获取 DOM 元素是必备技能。以下是 JS 中核心的获取元素方法&#xff0c;分为两大系列&#xff1a; 一、getElementBy... 系列 传统方法&#xff0c;直接通过 DOM 接口访问&#xff0c;返回动态集合&#xff08;元素变化会实时更新&#xff09;。…...

保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!

目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...

es6+和css3新增的特性有哪些

一&#xff1a;ECMAScript 新特性&#xff08;ES6&#xff09; ES6 (2015) - 革命性更新 1&#xff0c;记住的方法&#xff0c;从一个方法里面用到了哪些技术 1&#xff0c;let /const块级作用域声明2&#xff0c;**默认参数**&#xff1a;函数参数可以设置默认值。3&#x…...

大模型——基于Docker+DeepSeek+Dify :搭建企业级本地私有化知识库超详细教程

基于Docker+DeepSeek+Dify :搭建企业级本地私有化知识库超详细教程 下载安装Docker Docker官网:https://www.docker.com/ 自定义Docker安装路径 Docker默认安装在C盘,大小大概2.9G,做这行最忌讳的就是安装软件全装C盘,所以我调整了下安装路径。 新建安装目录:E:\MyS…...