《C 语言从代码示例入手》系列文章将带你开启 C 语言编程的探索之旅。通过大量简单且实用的代码示例,由浅入深地展现 C 语言的核心知识点,包括变量、数据类型、运算符、控制结构、函数等。每一个代码示例都有详细的解释和注释,让你能轻松理解代码的功能和运行原理,助你逐步掌握 C 语言的编程技巧,快速提升编程能力,为后续深入学习和开发打下坚实基础。
关于C语言的运行环境安装配置,请参看:【C 语言】从代码示例入手(零)
目录
四、企业链表
1、什么是企业链表
- 企业链表(也称为通用链表、侵入式链表)是 C 语言中一种灵活且高效的数据结构设计模式。
- 与普通链表不同,企业链表并不直接将数据包含在链表节点中,而是将链表节点嵌入到数据结构体中,使得数据可以以一种更通用的方式组织和管理。
2、普通链表与企业链表对比
(1)普通链表
普通链表的节点结构体通常将数据和指向下一个节点的指针组合在一起,例如:
typedef struct Node {
int data;
struct Node *next;
} Node;
(2)企业链表
企业链表将链表节点作为一个独立的结构体嵌入到数据结构体中,示例如下:
// 定义链表节点结构体
typedef struct ListNode {
struct ListNode *prev;
struct ListNode *next;
} ListNode;
// 定义包含链表节点的数据结构体
typedef struct {
int data;
ListNode list;
} MyData;
这种设计方式使得链表节点和数据分离,同一个链表可以存储不同类型的数据,提高了代码的复用性和灵活性。
(3)企业链表的重点优势
- 通用性强:可以将不同类型的数据结构体通过嵌入相同的链表节点结构体,存储在同一个链表中,提高了代码的复用性。
- 内存管理灵活:数据和链表节点的生命周期可以独立管理,便于动态分配和释放内存。
- 减少内存开销:避免了为每个数据项重复分配链表节点的额外开销,特别是在存储大量数据时,能显著节省内存。
3、链表的演化
重点说明:
- linux内核链表是将next指针放到下面,每次强转指针类型时,会出现问题,要想找到next指针的位置需要计算一下偏移量才可以
- 所以我们将next放到头部,这样无需要考虑偏移量问题了
4、企业链表的逻辑链接形式
5、头文件函数定义
LinkList.h
#ifndef LINKLIST_H
#define LINKLIST_H //防止头文件重复调用
//引入头文件库
////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
////////////////////////
/**
* 结构体:链表结点
* 链表的挂钩指针类型,每个结构体中加有这个挂钩
* 只需将这个挂钩指针连接起来即可实现链表
*/
typedef struct LINKNODE{
struct LINKNODE* next; //链表next指针
} LinkNode;
/**
* 结构体:链表
* 链表的挂钩指针类型,每个结构体中加有这个挂钩
* 只需将这个挂钩指针连接起来即可实现链表
*/
typedef struct LINKLIST{
LinkNode head; //小挂钩
int size;
} LinkList;
////////////////////////////////////
/**
* 结构体:人员
* 链表挂钩指针类型:LinkNode中含有一个next指针,Person类型可以强转为LinkNode类型
* !!!注意:LinkNode定义不能放到其它位置,因为链表指针访问时是前4个字节位置放到age下面后,访问的是name的内存了
*/
typedef struct PERSON{
LinkNode node;
char name[64];
int age;
} Person;
////////////////////////////////////
///////////////////////////
/**
* 遍历回调函数【函数指针】---【实现由用户决定】
* PRINT_NODE为函数名称,前面加*后就是函数指针了
*/
typedef void (*PRINT_NODE)(LinkNode*);
/**
* 比较回调函数【函数指针】---【实现由用户决定】
* PRINT_