顺序表 2 续集 c 实现增删查改

就四个部分 增 删 查 改

第一要明确 动态顺序表底层时数组,所以也是通过下标来进行实现运算

c 复制代码
#define SLtype int
 

上面宏定义 替换 顺序没关系

c 复制代码
typedef struct Seqlist {
    SLtype* arr;    // 指向动态数组的指针
    int size;       // 当前存储的元素个数
    int capacity;   // 当前数组的总容量
} SL;
 

所以需要得有个参数 是 指向数组首元素的地址 第一个

然后还要记录有效元素个数 就是size ,肯定要有个参数记录整个数组得总容量

size作为句柄,就是一个分界线得意思,就是区分有效数据和垃圾数据的分界线,根据

0下标开始原理 可以得出 arr[size] 指向最后有效元素的下一个

此图中 size 有效个数是 4 arr[size - 1] 才是最后一个元素

注: 这里0下标是标准,且实用,如果你开发出一种新语言也可以,启用你的规则 ,语法规定而已

所以 将下标和size结合起来 进行增删查改 起始也是数组的运算

先来新增吧,因为书接上集,我们在初始化的时候并没有赋值,而是,置为空 ,还有就是将size = capacity 都为 0 复习一下

这里整个数组的容量被指为0,需要后期去realloc增容

注意:由于我们初始化为空,没有空间容量capacity==0,所以在 插入(增加)/ 删除 之前都要 检测空间容量是否够用 我们显然不够用 所以要用realloc去增容,这是最开始没容量,还有就是在使用过程中也会容量不足,比方注册的客户比较多,需要判断,在每个用户使用时,避免出现问题,很严重,丢失一个数据,就要 等着卷铺盖走人吧 所以要检测是否有足够大的空间去使用而且去扩容 写个函数吧?

传过来的参数就是整个结构体指针变量?由于size总小于等于capacity所以就是说,当有效个数等于最大容量时就是满了,就要扩容,或者时本来就是0 没有容量的情况都统一扩容

首先理解两个判断的逻辑 (仅个人理解)

第一个 if 是判断是否有空间

第二个是判断realloc是否开辟扩容成功 也可以说是上保险 每个动态内存开辟的函数就基本都要这样判断,保证代码的健壮性

复制代码
void CheckCapacity(SL* psl) {
	if (psl->capacity == psl->size)//这里size<=capacity
	{
		
		//realloc(SLtype * arr, Newcapacity * sizeof(SLtype));
		
		if ( tmp == NULL)
		{
			perror("realloc  error!");
			exit(1);
		}
		psl->arr = tmp;
		psl->capacity = Newcapacity;
	}
}

int Newcapacity = (psl->capacity == 0) ? 4 : 2 * psl->capacity;翻译就是 如果没有容量了,就把容量赋值为4,反之就是将容量翻倍 变成两倍 这里你会问问什么不是其他倍数?3倍,4倍?and stuff. but 最好就是 2倍 ???

不问为什么 问什么? 本自具足,不假外求

三目操作符 就是简化的if-else

大白话语法 : 表达式 + ? + 语句1 + :+语句2;

如果说表达式结果为真 就执行语句1 否则 就语句 2;

复制代码
SLtype * tmp = (SLtype*)realloc(psl->arr, Newcapacity * sizeof(SLtype));

(SLtype*) 类型名 之前替换的是Int 指向那个数组的起始地址

SLtype * tmp(临时变量名)

(SLtype*) ------------------强制转化类型 暴力管用???

为社么呢? realloc 的返回值 是void *的类型 要转化为需要的

realloc (psl->arr, Newcapacity * sizeof(SLtype));

通过官网查询 图片可知,他的第一个参数是需要操作的空间的地址,第二个参数是 字节数 所以要用到 sizeof(类型 ) * 需要的数量 over? nonono

只是单方面的申请了,开辟指令,不一定会成功,也不一定会有足够的空间来给你 ,这是少数情况,但是就是要考虑极限,或者说是边界的情况 ,因为你永远也不会知道你的用户会有多逆天,你就要i把用户当作最没脑子,脾气还很爆的,性子还很急躁的250就好 所以还没完 要去判断是否开辟成功了

接下来就跟着我调试一下 看看结果

看到吗test01 那一行打个断点观察一下 然后 F5 开始调试 然后 F11 逐语句

第一个是 逐语句 看图标就知道 箭头指进去 就是 会进入到函数里一步一步的 一条语句的运行

第二个是逐过程

不管这一行写了多少条语句、多少个函数、多复杂,逐过程(Step Over)都一整行直接跑完,不进任何函数。 最关键结论

逐过程 = 执行当前行的全部内容,作为一个整体,不进入任何函数内部

下面就是刚打开的监视窗口 根据你的变量名来写

看左边的箭头 执行到这里啦 就是完成了初始化 不错 继续

调试完了 不错哦 很棒 终于初始化且检查空间完成

下一步 来个简单的销毁吧 SLdestroy

销毁两步走 必须两步缺一不可

1. free 释放空间 参数要求 地址

大白话语法 : free( 要释放的空间的地址/指针 )

free只是将内存空间释放 不会改变指针变量free 不改变指针,只释放空间;地址还在,但空间不归你了。

2. 改变指向 尽管这块空间被释放了但是 SLtype * arr的指向并没有改变 ,会让其指向已经释放的空间,就是野指针 就是一条野狗会乱咬人的 很危险 缺一不可

调试 可知确实销毁了

这里两个注释都和附近的代码是一种可以替换的关系 等价

这就是尾插代码

psl->arr[psl->size] = x; 解释一下 红色 表示地址 + 【偏移量(下标/索引)】 将下标和有效元素个数联系起来

psl->size++; <==> (psl->size)++;就是下标加一,向后空出一个位置 下标是最后一个有效元素的后一个

头插代码

你要想如果直接把他赋值给0号下标 ,肯定不行原来的数据就会被覆盖,明显不可以

如图所示,就是一个一个往后移动,但有个思考点? 是 1到2 2到3 and stuff no no no

明显会覆盖后面的数据 所以就好的方法就是 先把最后一个有效数据 往后移一下 就会腾出一个位置 (就是本来的位置),

一次移动后又会腾出一个空位 所以 最后会使得最开始 留出一个位置 ,用于头插 原理懂了 就可以写伪代码 接下来就是 代码的实现

1。循环移动后一位

2。将首位赋值为插入值

  1. 最后size++ ,插入了一个呀

任意位置的插入 主要理解 可以复用,就有头插和尾插的效果,当插入位置是arr[0] arr[size]时就是了

欲知后事 一起加油

不是一番寒彻骨,怎来的梅花香

相关推荐
han_hanker2 小时前
js 加减乘除精度问题2
开发语言·javascript·ecmascript
红目香薰2 小时前
Ascend C 算子:Sigmoid 函数原理深入解析与工程化构建及验证
c语言·开发语言·华为·华为云·昇腾·cann·modelarts
OTWOL2 小时前
C语言操作符终极揭秘:表达式求值秘籍
c语言·开发语言·c++
无巧不成书02182 小时前
Java 21 LTS 高级特性零基础通关:静态导入、项目目录规范、泛型全实战
java·开发语言·标准目录结构·泛型原理·类型安全实现
code monkey.2 小时前
【寻找Linux的奥秘】Linux 基础 IO 全解析:从 C 库到内核,吃透文件操作的底层逻辑
linux·c语言·基础io
Ancelin安心2 小时前
西工大noj(C/C++)100题参考题解及注意事项(2024)
c语言·c++·ide·windows·vscode·算法
张np2 小时前
java框架和http调用接口的区别
java·开发语言·http
李日灐2 小时前
【优选算法3】二分查找经典算法面试题
开发语言·c++·后端·算法·面试·二分查找·双指针
zzwq.2 小时前
PyMySQL 详解:从入门到实战,Python 操作 MySQL 一站式指南
开发语言·python