C语言 -- 链表(企业级,侵入式链表)

2023-11-09

目录

节点结构体的实现

初始化链表

插入链表

遍历链表

删除节点、销毁链表

用户test


侵入式链表,内核链表

普通单链表和侵入式单链表的区别在于:

  • 普通的单链表的结点指针域指向的是下一个结点的内存首地址;
  • 侵入式单链表的结点指针域指向的是下一个结点的指针域成员变量的内存首地址。

 

节点结构体的实现

节点结构体只维护指针域,用户需预留4个字节空间,供我们帮助连接数据。

//节点结构体
struct LinkNode
{
	//只维护指针域
	struct LinkNode* next;
};
//链表结构体
struct LList
{
	struct LinkNode pHeader; //头结点
	int m_size;  //链表长度
};
//暴露给用户的
typedef void* LinkList;

初始化链表

//初始化链表
LinkList init_LinkList()
{
	struct LList* mylist = malloc(sizeof(struct LList));
	if (mylist == NULL)
		return NULL;

	mylist->m_size = 0;
	mylist->pHeader.next = NULL;

	return mylist;
}

插入链表

//插入链表
void insert_LinkList(LinkList list, int pos, void* data)
{
	if (list == NULL)
		return;
	if (data == NULL)
		return;
	
	struct LList* mylist = list;
	if (pos<0 || pos>mylist->m_size - 1)
		pos = mylist->m_size;

	//取出用户数据的前四个字节空间
	struct LinkNode* myNode = data; //把void*类型的data转为一个指针,即4个字节大小

	//找到待插入位置的前驱节点
	struct LinkNode* pCurrent = &mylist->pHeader;

	for (int i = 0; i < pos; i++)
	{
		pCurrent = pCurrent->next;
	}
	//更新指针指向
	myNode->next = pCurrent->next;
	pCurrent->next = myNode;
	mylist->m_size++;
}

遍历链表

//遍历链表
void foreach_LinkList(LinkList list, void(*myPrint)(void*))
{
	if (NULL == list)
		return;
	struct LList* mylist = list;
	struct LinkNode* pCurrent = mylist->pHeader.next;  //指向第一个有真实数据的节点

	for (int i = 0; i < mylist->m_size; i++)
	{
		//pCurrent就是用户数据的首地址
		myPrint(pCurrent);
		pCurrent = pCurrent->next;
	}
}

删除节点、销毁链表

//删除链表节点之按位置删除
void removeByPos_LinkList(LinkList list, int pos)
{
	if (list == NULL)
		return;
	struct LList* mylist = list;
	if (pos<0 || pos>mylist->m_size - 1)
		return; //无效位置直接返回
	//找到待删除位置的前驱节点的位置
	struct LinkNode* pCurrent = &mylist->pHeader;
	for (int i = 0; i < pos; i++)
	{
		pCurrent = pCurrent->next;
	}
	//PCurrent就是待删除节点的前驱节点
	//利用一个指针记录待删除节点
	struct LinkNode* pDel = pCurrent->next;
	//更改指针的指向
	pCurrent->next = pDel->next;
	
	//free(pDel); //数据本身是用户开辟的,由用户自己管理释放
	mylist->m_size--;
}

//清空链表
// 用户的数据不需要我们来释放,只需要把头结点指向空即可
void clear_LinkList(LinkList list)
{
	if (list == NULL)
		return;
	struct LList* mylist = list;

	mylist->pHeader.next = NULL;
	mylist->m_size = 0;
}

//销毁链表
void destory_LinkList(LinkList list)
{
	if (list == NULL)
		return;

	free(list);
	list = NULL;
}

用户test

//给用户提供接口获取链表长度
int size_LinkList(LinkList list)
{
	if (list == NULL)
		return -1;
	struct LList* mylist = list;
	return mylist->m_size;
}


struct Person
{
	struct LinkNode node; //占用用户数据的前四个字节
	char name[32];
	int age;
};
//回调函数打印
void printPerson(void* data)
{
	struct Person* person = data;
	printf("Name:%s, Age:%d\n", person->name, person->age);
}


void test03()
{
	//初始化链表
	LinkList mylist = init_LinkList();
	//创建数据
	struct Person p1 = { NULL,"aaa",12 };
	struct Person p2 = { NULL,"bbb",13 };
	struct Person p3 = { NULL,"ccc",14 };
	struct Person p4 = { NULL,"ddd",15 };

	//插入数据
	insert_LinkList(mylist, 0, &p1);
	insert_LinkList(mylist, 0, &p2);
	insert_LinkList(mylist, 1, &p3);
	insert_LinkList(mylist, -1, &p4);

	foreach_LinkList(mylist,printPerson);
	printf("--------------------\n");
	removeByPos_LinkList(mylist,1);
	foreach_LinkList(mylist, printPerson);
	printf("--------------------\n");
	printf("链表长度 = %d\n",size_LinkList(mylist));
	clear_LinkList(mylist);
	printf("链表长度 = %d\n", size_LinkList(mylist));
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C语言 -- 链表(企业级,侵入式链表) 的相关文章

  • Linux搭建服务器之六:安装kafka

    windows安装kafka 请点击 https blog csdn net weixin 44039105 article details 129240685 spm 1001 2014 3001 5502 安装jdk https blo
  • 关于STM32串口烧录后程序正常运行,但是掉电或复位后程序不正常运行的可能解决方法。

    关于STM32串口烧录后程序正常运行 但是掉电或复位后程序不正常运行的可能解决方法 BOOT0 BOOT1 MODE 0 X FLASH 1 1 SRAM 1 0 ISP BOOT0置1 BOOT1置0 开启串口烧录模式 用FlyMcu烧录
  • 回首2021,展望2022

    律回春晖渐 万象始更新 2022年的曙光即将照射到这片平畴沃野 在这辞旧迎新的时刻 观成科技祝大家 新年快乐 吉祥如意 2021年 对于网络安全行业来说又是不平凡的一年 疫情反复 网络安全事件频发 网络安全的攻防对抗烈度和重视程度都达到了一
  • 区块链入门二:区块不可篡改

    区块链入门一 什么是区块链 在上一篇中 简单介绍了什么是区块链 这一篇主要介绍区块链的不可篡改的特性 首先我们来了解下哈希 Hash 算法 这是百度的描述 简单来说就是一种不可逆的摘要算法 哈希算法的目的就是为了验证原始数据是否被篡改 常用
  • 【满分】【华为OD机试真题2023 JAVA&JS】字母组合

    华为OD机试真题 2023年度机试题库全覆盖 刷题指南点这里 字母组合 知识点回溯 时间限制 1s 空间限制 256MB 限定语言 不限 题目描述 每个数字对应多个字母 对应关系如下 0 a b c 1 d e f 2 g h i 3 j

随机推荐

  • vue面试题汇总

    HTML篇 CSS篇 JS篇 TypeScript篇 React篇 微信小程序篇 前端面试题汇总大全 含答案超详细 HTML JS CSS汇总篇 持续更新 前端面试题汇总大全二 含答案超详细 Vue TypeScript React 微信小
  • MySQL索引底层:B+树详解

    前言 当我们发现SQL执行很慢的时候 自然而然想到的就是加索引 对于范围查询 索引的底层结构就是B 树 今天我们一起来学习一下B 树哈 Mysql有什么索引 索引模型是什么 树简介 树种类 B 树 B 树简介 B 树插入 B 树查找 B 树
  • python3 清除过滤emoji表情

    前段时间发现了一个 人工智能学习网站 通俗易懂 风趣幽默 分享一下给大家 学习链接 python3 清除过滤emoji表情 第一种方法 使用emoji处理库 安装emoji 使用 import emoji test str 服务周到 性价比
  • 汇编语言(王爽第三版)实验二

    实验二 题目预览 使用Debug 将下面的程序段写入程序 逐条进行 根据指令执行后的实际运行情况填空 仔细观察图3 19中的实验过程 然后分析 为什么2000 0 2000 F中的内容会发生改变 1 使用Debug 将下面的程序段写入程序
  • 目标跟踪整理(1)之MOSSE

    之前读过一遍MOSSE了 读完还是有一种懵懵的感觉 最近还需要入基于相关滤波的目标跟踪的坑 所以又屁颠屁颠跑来深入理解一下 毕竟是相关滤波的始祖啊 Visual Object Tracking using Adaptive Correlat
  • SpringMVC学习(一)——快速搭建SpringMVC开发环境(非注解方式)

    目录 1 开发环境准备 1 1 首先电脑需要安装JDK环境 略 1 2 准备一个以供开发的tomcat 1 3 准备Maven工具 1 4 准备IDE编译器 1 5 准备一个本地的数据库 2 搭建SpringMVC开发环境 2 1 创建we
  • Golang - restful-url的接口注册处理

    一 注册 根请求转到rootHandle 在rootHandle中为不同的url查找对应的处理接口并执行 1 tars业务端配置restful url与处理函数 指定url与对应的处理函数 type TarsHttpMux struct h
  • ubuntu20下安装配置x11vnc的步骤——多次亲测可用

    在Ubuntu 20 04中安装和配置x11vnc的步骤如下 打开终端并输入以下命令以安装x11vnc sudo apt get install x11vnc 安装完成后 输入以下命令以生成密码文件 sudo x11vnc storepas
  • 安徽大学研究生院计算机与科学,安徽大学研究生导师简介院系所计算机科学与技术学院姓名赵.doc...

    安徽大学研究生导师简介院系所计算机科学与技术学院姓名赵 安徽大学研究生导师简介 院 系 所 计算机科学与技术学院 姓名 赵姝 性别 女 出生年月 1979 10 导师类别 硕士生导师 技术职称 副教授 联系方式 zhaoshuzs2002
  • 数据预处理之重复值

    目录 0 前言 1 重复值的识别 1 1 DataFrame识别重复值 duplicated 1 2 Serier识别重复值 is unique 2 统计重复行的数量 duplicated sum 3 重复值的处理 0 前言 在实际数据采集
  • PYTHON飞机大战(第六天)

    OK 今天成功做出了多个外星人 代码来了 import sys import pygame from bullet import Bullet from alien import Alien def check keydown events
  • Java是动态语言吗?从《Java核心编程》探索真知

    目录 一 Java是动态语言吗 1 动态语言 2 静态类型 3 Java核心编程 中探索 为什么Java可以称之为 准动态语言 二 了解ClassLoader 1 类加载器 2 Bootstrap classLoader 3 URLClas
  • QT 添加背景图片,按钮不被覆盖

    QT设计窗体时 想添加背景图片 在设计器中 只需要右击窗体 gt 改变样式表 添加你想要的图片就可以了 不想覆盖按钮的话 主需要像上图那样就行了
  • LU分解的矩阵逆运算

    算法名称 矩阵求逆 基于LU分解法 LU分解算法评价 LU分解大约需要执行N3 3次内层循环 每次包括一次乘法和一次加法 这是求解一个 或少量几个 右端项时的运算次数 它要比Gauss Jordan消去法快三倍 比不计算逆矩阵的Gauss
  • Java菜鸟入门(20) Producer Consumer经典代码

    来自oracle官网 https docs oracle com javase 7 docs api java util concurrent locks Condition html class BoundedBuffer final L
  • U盘重装系统教程

    重装系统不管是U盘启动还是光盘启动 最终是否可以引导u盘装系统 很大取决于PE或者DOS系统能否识别出来U盘 一 准备工作 制作大白菜U盘启动盘 需要下载一个windows系统文件 就是win7系统 win10系统文件这类的 到U盘里 便可
  • 代理模式之静态代理

    一 什么是代理模式 代理模式 为其他对象提供一种代理 以控制对这个对象的访问 代理类的对象本身并不真正实现服务 我们在访问实际对象时 是通过代理对象来访问的 二 代理模式的分类 静态代理 代理和被代理之前都是确定的 都实现相同的接口或继承相
  • vue锚点定位(tab切换定位不同的div位置)

    1 效果演示 2 HTML部分 div class tabs div class info tit span class pointer css3 lang CN 集团简介 Group profile span span class poi
  • IntelliJ IDEA配置java环境以及解决IDEA不能直接运行单个JAVA文件

    写Java代码选择IEDA的原因是我之前用的Pycharm写python 而IEDA和pycharm几乎一模一样的用法 而且IEDE可以写Java Python等很多语言 只要安装了对应的插件 File gt Settings gt Plu
  • C语言 -- 链表(企业级,侵入式链表)

    目录 节点结构体的实现 初始化链表 插入链表 遍历链表 删除节点 销毁链表 用户test 侵入式链表 内核链表 普通单链表和侵入式单链表的区别在于 普通的单链表的结点指针域指向的是下一个结点的内存首地址 侵入式单链表的结点指针域指向的是下一