【线性表】
- 顺序存储:顺序表
- 链式存储:单链表、双链表、循环链表、静态链表
【顺序表的优缺点】
优点
(1)结构简单
(2)可直接定位到表中任一元素,并可随机存取元素,连续存取速度快。
缺点
(1)存储空间难于准确静态分配,分配大了浪费空间,分配小了又可能不够用。
(2)插入、删除操作不太方便,需移动大量数据元素,效率较低。
【单链表的优缺点】
优点
(1)存储空间动态分配,可以按需要使用。
(2)插入/删除结点操作时通过只要修改指针,不必移动数据元素。
缺点
(1)每一结点附加指针域。
(2)非随机存取结构,查找定位操作需从头指针出发顺着链表扫描。
【顺序表和链表的比较】重点
1、存取(读写)方式
顺序表:随机存取、顺序存取。
链表:只能从表头顺序存取元素。(不支持随机存取)
访问第i个位置,顺序表只需一次访问,链表需从表头开始依次访问i次。
2、逻辑结构与物理结构
顺序存储:逻辑上相邻的元素,对应的物理存储位置也相邻。
链式存储:逻辑上相邻的元素,物理存储位置不一定相邻,对应的逻辑关系是通过指针链接来表示。
3、查找、插入和删除操作(时间复杂度)
名称 | 访问 | 查找 | 插入 | 删除 |
---|---|---|---|---|
数组 | O(1) | O(n) | O(n) | O(n) |
有序数组 | O(1) | O( | O(n) | O(n) |
链表 | O(n) | O(n) | O(1) | O(1) |
有序链表 | O(n) | O(n) | O(n) | O(n) |
对于按值查找,顺序表无序时:顺序表O(n)、链表O(n)
顺序表有序:可采用折半查找O()
对于按序号查找:顺序表O(1)、链表O(n)
链表每个结点都带有指针域,故存储密度不够大。
4、空间分配
顺序存储在静态存储分配情形下,一旦存储空间装满就不能扩充,若再加入新元素,则会导致内存溢出,因此需要预先分配足够大的存储空间。预先分配过大,可能会导致顺序表后部大量元素闲置;预先分配过小,又会造成溢出。
动态存储分配虽然存储空间可以扩充,但需要移动大量元素,导致操作效率降低,而且若内存中没有更大块的连续存储空间,则会导致分配失败。
链式存储的结点空间只在需要时申请分配,只要内存有空间就可以分配,操作灵活、高效。
【时间复杂度例题】
例1、在n个元素的线性表的数组表示中,以下操作时间复杂度为
(1)访问第i()个结点和求第i(
)个结点的直接前驱
解析:对于数组,无论是否有序,按序号查找(访问)均为O(1)
(2)在最后一个结点后插入一个新的结点
解析:在最后位置插入新结点不需要移动元素,时间复杂度为O(1)
(3)删除第一个结点
解析:被删结点后的结点需依次前移,时间复杂度为O(n)
(4)在第i()个结点后插入一个结点
解析:需要后移n-i个结点,时间复杂度为O(n)
例2、设线性表有n个元素,严格来说,以下操作中,在顺序表上实现要比链表上实现的效率有何不同
(1)输出第i()个元素值
解析:顺序表O(1),链表O(n)
(2)交换第3个元素与第4个元素的值
解析:顺序表只需3次交换操作,链表则需分别找到两个结点的前驱,第4个结点断链后再插入到第2个结点后,效率较低
若:交换第1个元素和第二个元素,则顺序表和链表效率差不多
(3)顺序输出这n个元素
解析:均需依次顺序访问每个元素,时间复杂度相同
例3、设线性表中有2n个元素,在单链表上实现和顺序表上实现有何不同
(1)删除所有值为x的元素
解析:单链表和顺序表上实现的时间复杂度都为O(n),但顺序表需移动很多元素,则单链表效率高
(2)在最后一个元素的后面插入一个新元素
解析:在最后一个元素后插入新元素,顺序表和链表均不需要移动元素,则仅需考虑查找效率,相比于链表,顺序表查询效率高,因为其内存地址是连续的,所以读取每个元素的时间周期更短、更快
例4、给定有n个元素的一维数组,建立一个有序单链表的最低时间复杂度是O()
例5、将长度为n的单链表链接在长度为m的单链表后面,其算法的时间复杂度采用大O形式表示应该是O(m)
解析:先遍历长度为m的单链表,找到该单链表的尾结点,然后将其next域指向另一个单链表的首结点,其时间复杂度为O(m)