数据结构----线性表之链式存储
以下内容只是学习记录:
一、链式存储定义
用一组任意存储位置存储数据元素,存储位置可以连续也可以不连续,存储格式如下图:
由结构图可以看出链式存储相比于顺序存储
优点:
1、插入删除灵活,只需修改指针即可
2、内存动态分配,无需像顺序表那样存储空间不够需要额外写代码动态增加存储空间
缺点: 1、存储密度小,即存储空间利用率低
2、查找数据没有顺序表方便,顺序表可以通过下标直接计算存储地址,而单链式结构查找数据需要从表头开始一个一个查找
二、链式存储实现
单链表代码实现:
1、创建单链表结构体
1 2 3 4 5 6 7 8 | #define ElemType int typedef struct ListNode { ElemType data; //数据域 struct ListNode *next; //指向下一个节点的指针 }ListNode; typedef ListNode* List; //给ListNode*重新起个名字 ,关于结构体的定义以及使用,请参考博客: |
2、定义一个单链表并初始化为NULL
1 2 3 4 5 6 7 8 9 10 11 | void InitList(List *head) { (*head) = NULL; } void main() { List mylist ; //List表示类型为ListNode结构体的指针变量 InitList(&mylist); //这里必须要传入mylist的地址,否则就是拷贝传递,最终返回时,mylist还是没有改变 printf ( "%p" ,mylist); } |
代码解析:
3、创建链表并赋值
(1) 头插法
下图为头插法示意图,即在头节点和链表之间插入一个节点
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 | void HeadCreatList(List *head) { for ( int i = 1; i < 10; i++) { ListNode *s = (ListNode *) malloc ( sizeof (ListNode)); assert (s != NULL); s->data = i; s->next = (*head)->next; (*head)->next = s; } } |
注:使用头节点的好处:
1、火车跑得快全靠火车头,链表要安全全靠头节点,可以保护头节点不变
2、代码实现较简单。不信?你可以自己动手写一个不带头节点的链表实现,对比一下!
3、可以用头节点数据区存储链表的额外信息,比如链表的长度等,这样计算链表长度直接查询头节点即可获得
使用头节点的好处:
占用空间增大,但我认为这点头节点占据的存储空间相比较它带来的好处可忽略
(2) 尾插法
下图是尾插法示意图
代码如下:
1 2 3 4 5 6 7 8 9 10 11 | void TailCreatList(List *head) { ListNode *p = *head; for ( int i = 1; i < 10; i++) { p = p->next = (ListNode *) malloc ( sizeof (ListNode)); assert (p != NULL); p->data = i; p->next = NULL; } } |
(3)显示链表
1 2 3 4 5 6 7 8 9 10 | void ShowList(List head) { ListNode *p = head->next; //head指向的下一个节点数据才是真正的数据开始 while (p != NULL) { printf ( "%d-->" , p->data); p = p->next; } printf ( "Nul.\n" ); } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· 因为Apifox不支持离线,我果断选择了Apipost!