链表和顺序表

本文详细介绍了线性表的概念、顺序表和链表的存储结构、特点以及优缺点。顺序表通常采用数组存储,链表则通过指针链接元素。顺序表支持随机访问,但在插入和删除操作时效率较低。链表在插入和删除操作上有优势,但不支持随机访问。两者在内存管理和应用场景上各有侧重。

一、线性表

  • 线性表(linear list)是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串…
    线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。
    在这里插入图片描述
    线性表的存储结构
    在这里插入图片描述

  • 特征:
    1、集合中必存在唯一的一个“第一元素”
    2、集合中必存在唯一的一个“最后元素”
    3、除最后一个元素之外,均有唯一的后继(后件)
    4、除第一个元素之外,均有唯一的前驱(前件)

  • 结构特点:
    1、均匀性:虽然不同数据表的数据元素可以是各种各样的,但对于同一线性表的各数据元素必定具有相同的数据类型和长度。
    2、有序性:各数据元素在线性表中的位置只取决于它们的序号,数据元素之前的相对位置是线性的,即存在唯一的“第一个”和“最后一个”的数据元素,除了第一个和最后一个外,其它元素前面均只有一个数据元素(直接前驱)和后面均只有一个数据元素(直接后继)。
    在这里插入图片描述

二、顺序表

  • 概念及结构
    顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成为数据的增删查改。
    在这里插入图片描述

顺序表一般可以分为:
1、静态顺序表:使用定长数组存储
2、动态顺序表:使用动态开辟的数值存储

在这里插入图片描述

//顺序表的静态存储
#define N 100
typedef int SLDataType;
typedef struct SeqList
{
      SLDataType array[N];//定长数组
      size_t size;//有效数据的个数
 }SeqList;

//顺序表的动态存储
typedef struct SeqList
{
       SLDataType* array;//指向动态开辟的数组
       size_t size;//有效数据个数
       size_t capacity;//容量空间的大小
}SeqList;

顺序表的动态存储:
在这里插入图片描述

  • 顺序表的短板
    1、插入元素,时间复杂度O(n)
    插入为第i个元素,则需要移动n-i+1个数据元素,需要移动第n到第i个元素。
    均值的计算:一共为(n+1)(n+0)/2,因为一共计算插入了n+1个位置。则均值为:n/2
    在这里插入图片描述
    2、删除元素,时间复杂度 O(n)
    删除 第 i 个 元素,则需要移动 n - i 个数据元素 。 需要移动 第 i+ 1 到 第 n 个 元素。
    均值的计算:一共为 (n)(n-1+0) / 2 ,因为一共计算删除 n 个位置。则均值为 : (n-1) / 2
    在这里插入图片描述

三、链表

  • 概念
    链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
    链表是一种有序的列表。链表的内容通常存储与内存中分散的位置上。链表由节点组成,每一个结点的结构都相同。节点分为数据域或链域,数据域顾名思义就是存放节点的内容链域存放的是下一个节点的指针,也就是螳螂捕蝉黄雀在后的道理。
    在这里插入图片描述
  • 链表结构
    1、单向、双向
    在这里插入图片描述
    2、带头、不带头
    在这里插入图片描述
    3、循环、非循环
    在这里插入图片描述
    在这里插入图片描述
    1. 无头单向非循环链表结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结 构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。
    2. 带头双向循环链表结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向 循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而 简单了,后面我们代码实现了就知道了。

四、顺序表和链表的区别和联系

  • 顺序表和链表的比较
    1、顺序表:顺序表的特点是逻辑上相邻的数据元素,物理存储位置也相邻,并且顺序表的存储空间需要预先分配。

    • 优点
      1)方法简单,各种高级语言中都有数组,容易实现。
      2) 不用为表示节点间的逻辑关系而增加额外的存储开销。
      3) 顺序表具有按元素序号随机访问的特点。
  • 缺点
    1)在顺序表中做插入、删除操作时,平均移动表中的一半元素,因此n较大的顺序表效率低。
    2) 静态分配,程序执行之前必须明确规定存储规模预先分配足够大的存储空间,估计过大,可能会导致顺序表后部大量闲置;预先分配过小,又会造成溢出。

    2、链表:
    在链表中逻辑上相邻的数据元素,物理存储位置不一定相邻,它使用指针实现元素之间的逻辑关系。并且,链表的存储空间是动态分配的。

  • 优点
    插入、删除运算方便。

  • 缺点
    1)要占用额外的存储空间存储元素之间的关系,存储密度降低。存储密度是指一个节点中数据元素所占的存储单元和整个节点所占的存储单元之比。
    2)链表不是一种随机存储结构,不能随机存取元素。

  • 顺序表和链表的区别
    1、顺序表和链表都具有增、删、查、改的相同功能,但算法复杂度却不相同。

  • 增:
    1) 顺序表往指定位置,不覆盖的添加一个值,后面的值日要往后移动,算法复杂度为O(n);
    2)链表往指定位置添加一个节点,需要从表头遍历到指定位置,算法复杂度为O(n),如果带有索引的节点,算法复杂度为O(1)。


  • 1) 顺序表指定位置,删除一个值时,需要将后面的值向前移动,算法复杂度为O(n);
    2) 链表指定一个位置,删除一个时,如果没有对指定节点进行索引,需要从表头遍历到指定位置,然后将指定节点删除,算法复杂度为O(n), 如果对指定节点做索引,删除节点的算法复杂度为O(1)。


  • 1) 顺序表直接查询指定位置值算法复杂度为O(1);
    2)链表需要遍历节点到指定位置,算法复杂度为O(n);如果节点指定位置节点有索引,算法复杂度为O(1).

  • :修改其实就是查找修改值的位置,再对值进行修改。
    1)顺序表的增和删表数量规模比较大时,平均移动一半的元素,效率不高。
    2) 对于有索引的链表,添加和删除只需要O(1)算法复杂度,效率高。因此,链表用于频繁的添加和删除数据时,有优势。

    2、从内存角度
    (1)顺序表是由数组组成的线性表,数组是一组地址连续的单元存储块,分配于栈区,可以自动释放。
    (2)链表是由不连续的地址节点组成的线性表,每个节点可以是一个单元的地址块或连续地址块,分配于堆区,节点必须手动释放。内存管理比较不方便。

    3、时间上的比较(Time)

    • 访问随机元素的时间复杂度:
      因为顺序表的结构就像是数组一样,可以用下标来访问它的元素,所以它的元素是支持随机访问的;相比之下,单链表的数据是链式存储的,它的元素是不支持随机访问的,想要知道某个元素,只能从头结点开始遍历整个链表,知道找到了该元素为止。因此顺序表访问随机元素的时间复杂度是O(1),而单链表访问随机元素的平均时间复杂度是O(n)。

    • 随机位置插入、删除元素的时间复杂度:
      因为顺序表的元素是连续存储的,因此要在特定位置插入、删除元素需要把它之后的元素全部后移或前移一个元素的位置,时间开销很大;而单链表在插入或删除元素时,只需要改变它的前驱元素及插入或删除元素的指向即可。因此,顺序表在插入随机位置插入、删除元素的平均时间复杂度是O(n),单链表在插入随机位置插入、删除元素的时间复杂度是O(1)。

      一般来说线性表(顺序表和单链表都属于线性表)的插入删除操作会被执行的频繁一些,因此,使用单链表的频率较大。

顺序表和链表区别:
共同点:
1.都是线性表
2.元素逻辑存储上是连续的
3.每个元素都有唯一的前驱以及唯一的后继。注意:第一个元素没有前驱,最后一个元素没有后继—循环链表除外
不同点:
1.底层存储空间不同:顺序表底层空间是连续的链表底层空间不连续
⒉插入和删除方式不同:
顺序表任意位置插入和删除需要搬移大量的元素,效率低,时间复杂度为O(N)
链表任意位置插入和删除不需要搬移元素,效率高,时间复杂度为O(1)
3.随机访问:
顺序表底层空间连续,支持随时访问,访问任意位置元素时间复杂度为O(1)
链表底层空间不连续,不支持随机访问,访问任意位置元素时间复杂度为O(N)
4.扩容:
顺序表在插入时候需要进行扩容—开辟新空间、拷贝元素、释放旧空间
链表:插入时候不需要进行扩容
5.空间利用率:
一般情况顺序表空间利用率比较高
链表中的元素存储在一个一个的节点中,而每个节点都是malloc出来的:频繁向堆申请小的内存块–内存碎片、效率低
6.应用场景不同:
顺序表适合:元素高效存储以及随机访问操作比较多的场景
链表:适合任意位置插入和删除比较频繁的场景
7.缓存利用率:链表的缓存利用率比顺序表低

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值