在我们学完C语言之后 我们准备写一个贪吃蛇的代码
但在我们写贪吃蛇代码之前 我们需要铺垫一些数据结构的知识
- 顺序表
- 基于顺序表实现通讯录项目
- 单链表
- 双向链表
-
顺序表(底层是数组)
顺序表其实是线性表(具有相同特性的数据结构的集合)的一种
线性表的物理地址不一定连续,这主要取决于线性表的存储结构。但其逻辑结构是连续的。
线性表主要有两种存储结构:顺序存储结构和链式存储结构。
常见的线性表实现方式有顺序存储(如数组)和链式存储(如链表)两种。顺序存储的线性表在物理内存中是连续存储的,访问速度快,但插入和删除操作可能需要移动大量元素。链式存储的线性表则通过指针链接各个元素,插入和删除操作较为方便,但访问速度可能较慢。
在顺序存储结构中,逻辑地址和物理地址都是连续的。这是因为顺序存储结构通常使用数组来实现,数组在内存中的存储是连续的,因此逻辑上相邻的元素在物理地址上也是相邻的。
然而,在链式存储结构中,情况就不同了。链式存储结构是通过指针或链接来建立数据元素之间的逻辑关系。在这种结构中,逻辑地址是连续的,但物理地址并不一定连续。每个元素在内存中占据一个存储单元,元素之间的逻辑关系是通过存储单元中的指针来指示的。因此,即使逻辑上相邻的元素,它们在物理内存中也可能相距很远。
总的来说,线性表的物理地址是否连续取决于其存储结构。顺序存储结构保证物理地址的连续性,而链式存储结构则允许物理地址的非连续性。这种灵活性使得链式存储结构在处理某些问题时(如插入和删除操作频繁的情况)更加有效。
顺序表的特性:
物理结构:连续
逻辑结构:连续
顺序表分类
静态顺序表(定长数组)
静态顺序表的定义:
数组大小给小了 空间不够用
数组大小给大了 空间浪费
其实定长数组我们已经使用的够多了 接下来我们讲讲动态内存开辟的数组--动态顺序表
动态顺序表(动态内存开辟的数组)
动态顺序表的定义:
当我们的空间不够时 我们便进行动态增容 动态数组会比定长数组更加的灵活
现在我们用代码来实现动态顺序表
我们使用头文件.h 和源文件.c来编程 当然也可以在一个源文件中写 但这会让代码比较冗杂
我们数据结构中 其实重要的就是四个操作:增删查改
当然还有初始化 销毁.....
我们这里要有一个习惯 每写一个操作之后 去测试该代码是否有效 不要等到所有代码写完再去测试 会比较难测试出来或者修改代码量会比较大
SeqList.h
- 我们首先给int创建一个别名SLDataType 这是为了方便之后的修改 比如说,我们想让数组arr为char类型 我们只需要改动一次 即:typedef char SLDataType
- 我们创建了一个结构体类型struct SeqList 并给其起了个别名为SL
- 在结构体类型中 有三个成员 有一个数组arr size表示有效数据个数--也是数组最后一个元素的下标值+1 capacity表示为该数组分配的空间大小
- 接下来 我们声明了一些操作 如:初始化 销毁 增删查改等操作
SeqList.c
- 在该段代码中 我们需要注意的就是扩容代码的实现
在数据结构和算法的设计中,为了优化性能、减少内存分配的次数以及避免频繁的内存重新分配,开发者经常会采用一些启发式的方法来确定初始分配的空间大小或增长因子。乘以2或3是一种常见的选择,因为它提供了一个相对简单的增长策略,同时也在很多情况下提供了较好的性能。
所以我们在分配空间大小时 让其乘以2
在这里建议大家 在理解代码后 自己动手去实现一下 可能就发现自己会漏掉一些必要的代码 在手敲代码时 如尾插 头插时 我们可以通过画图的方式 增加自己的理解 但还需要告诉大家的是 动态顺序表的实现并不是只有这一种代码 我这里的代码只是我学习到的 或许你们的更加全面 并不需要完全照搬的 按照你的思路来敲一遍吧
基于顺序表实现通讯录项目
我们知道通讯录应该包含:姓名 性别 年龄 电话 住址等信息
功能要求:
增加联系⼈信息
删除指定联系⼈
查找制定联系⼈
修改指定联系⼈
显⽰联系⼈信息
Contact.h
需要注意的点 我已经在代码中给了注释 可能会有缺少 待我发现后或者有人提醒后 便进行改正
Contact.c
这里我就不对该代码进行解读了 其实更多还是基于顺序表的操作 其余则很简单了
一定要记得在完成一个操作的代码后 去测试一下该代码功能是否与期望相同
我的test.c中 我是写了个菜单
test.c
现在我运行下 当前我的代码
然后根据输入的操作命令来进行
大致代码如此 后面的操作我便不给大家演示了