顺序表的知识

文章讨论了空间复杂度的概念,强调它与内存占用的区别,并举例解释了递归调用时的空间复杂度。此外,提到了字符串函数strstr和内存操作函数memcpy与memmove的用途及时间复杂度。文章还对比了线性表(如顺序表和链表)与非线性表(如树和图),并讲解了如何使用qsort排序顺序表以及链表的操作。最后,分析了顺序表和链表各自的优缺点。
摘要由CSDN通过智能技术生成

目录

1.空间复杂度

2.strstr函数

3.memcpy  和memmove

4.线性表和非线性表

5.使用qsort排序顺序表

6.为什么有顺序表了还要有链表

7.单链表的增删查改


1.空间复杂度

空间复杂度不是内存所占的大小,而是变量的个数,且与变量是什么类型无关。

记住是额外创建的,外面传入的不算。空间复杂度基本上都是O1或者On

有例外比如说开个二维数组可能就是O(n^2)

若数组的最后一个下标是N 则你应该malloc n+1个 因为数组下标是从0开始的

易错1:

这个空间复杂度是O(n),递归要不断的创建函数和变量的栈帧,每个栈帧你可以认为它里面有常数个变量,创建n+1次栈帧 空间复杂度是O(n) 

函数栈帧的创建就像借东西一样,向操作系统借一块空间,用完之后还给操作系统,之后操作系统还能把这块空间继续借给别人使用

调用这俩函数 发现他们的变量的地址是相同的,说明占据相同的栈帧。 

而递归调用,假设从F(N)递归到F(1),从始F(N)创建  至终F(1)函数栈帧一直创建,先递,然后再一个个的归。

原因是递归的栈帧创建只要不return它就一直存在

易错2:

 这个递归是如何调用的呢?先调用Fib(N-1)一直往下调用,知道遇见Fib(2)返回。然后在调用Fib(N-2)。可惜的是Fib(N-2)调用的空间全部在Fib(N-1)这些递归调用之前所开辟的栈帧里面(已经还给了操作系统)。所以它的空间复杂度是O(n)。

它的时间复杂度是O(n^2).

这个体现了:时间是一去不复返的,调用一次栈帧就要花费一次时间。而空间是可以重复利用的。

2.strstr函数

3.memcpy  和memmove

他们都是按一个个字节来替换内存的

都是把n大小的字节,从str2开始覆盖到str1中,值得注意的是memmove包括了内存重叠的情况,memcpy不包括内存重叠的情况。一般用memmove就行。 memcpy效率更高,但是可能有内存重叠问题。

他们的时间复杂度都是O(N)

4.线性表和非线性表

线性表:顺序表 链表 队列  栈 字符串    

数据是挨着存储的(adjoin)

非线性表:树 图

顺序表就是数组,可以扩容的数组。注意malloc的时候第二个变量是字节的大小不是扩容元素的数量,别忘了乘以sizeof

free使用的时候不能free掉malloc出来的一部分。只能一起释放。还有free出问题了可能是野指针,也可能是malloc出来的对象越界访问,比如开辟了40个字节,却访问了第41个字节。

realloc 分为原地扩容和异地扩容 

原地扩容效率很高 ,要求是后面有足够大的空间。

异地扩容有代价,就是要拷贝原来的元素,然后在存入新的大的内存中去,再返回这个新的大的内存的地址      ,然后再把原来的小的内存释放掉。

realloc缩放还是扩大都是对使用权限进行操作的

申请空间malloc之类的,释放空间free之类的都是对使用权进行操作的  申请使用权对操作系统,和还给操作系统

5.使用qsort排序顺序表

第一个是要排序的元素的地址

第二个参数是排序多少个 

第三个是每个的字节数

第四个是compare函数 自己写的,注意compare函数传入的参数要带const修饰不然不对

数组最后一个位置的下一个位置的下标就是数组的个数

6.为什么有顺序表了还要有链表

顺序表是顺序存储,是一块连续的内存空间,头插 头删 以及中间的插入和删除都要动员整个数组,代价比较。顺序表可以根据下标来随机访问,而链表只能顺序访问,通过一个个的链子来访问。链表元素的插入和删除比较方便。

顺序表的缺点:

1.中间插入和删除以及头部插入和删除代价大,O(n)

2.空间不够要扩容,扩容的代价比较大。尤其是异地扩容,还有一定的空间浪费。

链表我们将单链表和带头循环双向链表

7.单链表的增删查改

结构体不能这样写,这是因为编译器查找类型,函数,变量是从上面查找的 ,即使函数写在下面也要声明。

为什么链表的Print不用assert

为什么顺序表就要断言,因为顺序表指针指向的是个结构体,结构体 里面有指针,size和capacity

单链表的尾插:首先再main函数定义头节点让它赋值为NULL然后需要改变这个指针就要传入二级指针,首先malloc一个新的节点,初始化这个节点(值和next),然后判断phead为空只需让phead指向新节点即可,如果不为空遍历找到最后一个节点,cur->next=newnode即可

要改Int 参数传入int* 

要改int* 参数传入 int**

要改结构体指针 list *p 传入 list**p 

要改结构体的成员,需要结构体指针。要改内容传入的参数总是高一级

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值