链表和顺序表

一、线性表

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

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

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

二、顺序表

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

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

链表和顺序表_第5张图片

//顺序表的静态存储
#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
    在这里插入图片描述

三、链表

  • 概念
    链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
    链表是一种有序的列表。链表的内容通常存储与内存中分散的位置上。链表由节点组成,每一个结点的结构都相同。节点分为数据域或链域,数据域顾名思义就是存放节点的内容链域存放的是下一个节点的指针,也就是螳螂捕蝉黄雀在后的道理。
    链表和顺序表_第6张图片
  • 链表结构
    1、单向、双向
    链表和顺序表_第7张图片
    2、带头、不带头
    链表和顺序表_第8张图片
    3、循环、非循环
    链表和顺序表_第9张图片
    链表和顺序表_第10张图片
    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)。

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

你可能感兴趣的:(数据结构,链表,算法,数据结构)