一.逻辑结构:
二.物理结构/存储结构:
1.顺序表:
-
优点:顺序表采用顺序存储的方式实现了线性表,由于采取了顺序存储,而且各个数据元素的内存大小相等,因此只需要知道该顺序表的起始地址即可立即找到某个元素在该顺序表中的位置,也就是顺序表拥有随机存取的特性,顺序表的每个结点中只需要存储数据元素本身即可(单链表每个结点中除了存储数据元素本身外还需要存储指向下一个结点的指针),因此顺序表的存储密度要比链表高
-
缺点:顺序存储的存储结构要求系统分配一整片连续的存储空间,所以在给顺序表分配空间时会较繁琐,并且顺序表的容量一开始就固定了,想要改变顺序表的容量也会较繁琐(因为改变容量后可能数据溢出如减小顺序表容量导致数据溢出)
2.链表:
-
优点:链表采用链式存储的方式实现了线性表,链表由于各个结点是离散的存放在空间中,所以添加一个结点时只需要动态地申请一小片的空间即某一个结点空间即可,同时由于各个结点的存储空间不要求连续,因此改变容量大小也会较容易
-
缺点:链式存储的缺陷就是当查询某个数据元素时只能从第一个结点(头结点)开始依次往后遍历寻找,所以链表(链式存储)是不可以随机存取的,而且各个结点中除了存储数据元素外,还需要花费一定的空间来存储指向下一个元素的指针,所以链表的存储密度比顺序表低
三.基本操作:
销毁操作在考研中出现频率较少,但实际操作中是非常重要的;
改操作其实只要实现了查操作后进行赋值即可修改;
a.创建操作:
-
顺序表:创建顺序表时由于顺序表要求分配一整片连续的存储空间,所以初始化顺序表时就需要预分配大片连续空间,如果一开始分配的空间较小,后期拓展容量时会很不方便,但一开始分配的空间过大,又会浪费内存空间
-
链表:创建链表时只需要申明一个头结点(头指针),并且分配一个头结点所需要的空间即可,当然链表也可以是无头结点的,无论链表有没有头结点,对于链表来说,之后如果想要拓展链表容量时,其实很方便,只需要再申请一小片新的空间,然后再用指针的方式把这个新结点连接到链表中即可,所以链表的存储容量的可拓展性(灵活性)要比顺序表强
-
总结:顺序表无论是采用静态分配(静态数组)还是动态分配(动态数组),都会导致数据变动量大,灵活性低于链表,所以在创建时优先考虑链表
b.销毁操作:
-
顺序表:销毁顺序表首先要把顺序表的长度修改为0即顺序表变为空表,这是在逻辑上把顺序表标记为一个空表,但顺序表占用的存储空间实际上分为两种情况->1.如果顺序表采用静态分配的方式实现,那就意味着顺序表占用的存储空间是通过申明一个静态数组的方式来请求系统分配的,这种情况下这片存储空间的回收是由系统自动进行的,当定义的静态数组的生命周期结束时系统会自动把这片空间回收(申明一个变量来申请空间,当变量的生命周期结束时系统也会自动把这个变量回收),也就是说顺序表采用静态分配方式时对于空间回收是不需要手动操作的,只需要手动把顺序表长度改为0即可;2.如果顺序表采用动态分配的方式实现,也就是说动态数组是用malloc函数申请的一片空间,这种情况下就需要手动地把这片空间free掉,由malloc函数申请的内存空间是属于内存当中的堆区域,在堆区域的内存空间不会由系统自动地回收,也就是说需要手动free掉来实现回收
-
链表:销毁链表本质就是把链表中的各个结点依次删除,所以对于链表的销毁操作核心就是一个free函数,可以写一个循环,依次扫描各个结点,把各个结点都free掉,这样就可以把链表中各个结点占用的空间都给回收(注:链表的结点也是由malloc函数申请的)
-
注:用malloc函数手动申请的空间,那就必须手动用free函数销毁
c.增加操作&删除操作:
-
顺序表:由于顺序表采用顺序存储的方式,要求各个数据元素在内存中是相邻且有序的,所以当插入/删除元素都需要把此次操作的位置之后的元素都给后移/前移->插入元素就后移,删除元素就前移,对于顺序表,插入/删除元素的最坏时间复杂度(插在顺序表第一个位置,就需要移动所有元素)和平均时间复杂度都为数量级O(n),时间开销主要来自移动元素
-
链表:由于链表采用链式存储的方式,所以插入/删除元素只需要修改指针即可,链表的插入/删除元素的时间复杂度也是O(n),链表的时间开销主要来自查找目标元素,因为链表不具有随机存取的特性,要想找到要插入的位置,只能从第一个元素循环遍历依次往后查找,直达找到要插入的位置或者找到要删除的数据结点
-
总结:虽然顺序表和链表插入/删除元素的时间复杂度都是数量级O(n),但如果数据量非常大时,移动元素付出的时间代价要比查找元素的代价大,也就是说单链表在插入/删除元素时要优于顺序表
d.查找操作:分为按位查找和按值查找
-
顺序表:对于按位查找,要想找到某一个位序的元素所存放的位置只需要O(1)的时间复杂度,也就是说顺序表具有随机存取的特性;对于按值查找,如果顺序表中的各个数据元素的排列本来就是无序的,那么只能从第一个元素开始依次往后对比,所以时间复杂度为数量级O(n),如果顺序表中的各个数据元素的排列是有序的,则可以使用某些查找算法如折半查找在更短的时间内找到目标元素
-
链表:链表只能从第一个结点开始依次往后遍历查找,所以它的按位查找的时间复杂度为数量级O(n);链表中的数据元素无论是有序还是无序,进行按值查找时都只能从第一个数据元素开始依次往后遍历,因此时间复杂度就是数量级O(n)
-
查找操作中综合来看顺序表比链表更高效
四.总结:
例如排队适合用链表,因为队伍长度无法预估;一个班级的人数可用顺序表,因为一个班的人数可准确得知;
五.开放式问题的答题思路:
讨论基本操作时也要考虑效率。