数据结构学习笔记--线性表(顺序存储和链式存储)

线性表(顺序存储和链式存储)

文章目录

  • 线性表(顺序存储和链式存储)
  • 一、线性表的定义
  • 二、顺序存储结构
    • 1.定义
    • 2.顺序存储结构的插入与删除
      • 获取元素操作
      • 插入操作
      • 删除操作
      • 时间复杂度分析
    • 3.顺序存储结构的优缺点
  • 三、链式存储结构
    • 1.定义
      • 头指针与头结点的异同
    • 2.单链表的各种基本操作
      • 读取元素
      • 插入元素
      • 删除元素
      • 整表创建
      • 整表删除
    • 3.单链表结构与顺序存储结构的比较
  • 总结


一、线性表的定义

线性表是零个或多个数据元素的有限序列。 线性表是一个序列,元素之间是有顺序的,并且线性表强调是有限的,即元素的个数是有限的。
将线性表元素的个数n定义为线性表的长度,当n=0时,称为空表。在比较复杂的线性表中,一个数据元素可以由若干个数据项组成。
抽象数据类型定义:

  • 线性表的数据对象集合为{a1,a2,a3,…,an},每个元素的类型均为DataType。其中,除第一个元素a1之外,每一个元素有且只有一个直接前驱元素,除了最后一个元素an外,每一个元素有且只有一个直接后继元素。数据元素之间的关系是一对一的关系。
  • 操作:
    数据结构学习笔记--线性表(顺序存储和链式存储)_第1张图片
    线性表有两种物理结构:1.顺序存储结构。2.链式存储结构。

二、顺序存储结构

1.定义

线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表的数据元素。在编程语言中通常使用一维数组的形式实现。

2.顺序存储结构的插入与删除

获取元素操作

获取元素即将线性表中第 i 个元素返回,只需要i的数值在数组下标范围内,将数组第 i-1 下标的元素返回即可。

插入操作

插入算法思路:

  1. 如果插入位置不合理,抛出异常;
  2. 如果线性表的长度大于等于数组长度,则抛出异常或动态增加容量;
  3. 从最后一个元素向前遍历到第 i 个位置,分别将它们都向后移动一个位置;
  4. 将要插入的元素填入位置 i 处;
  5. 表长加1.

删除操作

删除算法思路:

  1. 如果删除位置不合理,抛出异常;
  2. 取出删除元素
  3. 从删除元素位置开始遍历到最后一个元素位置,分别将它们都向前移动一个位置;
  4. 表长减1

时间复杂度分析

显然,查找的时间复杂度维O(1),而插入和删除操作涉及到遍历元素让元素移动,所以插入和删除操作的时间复杂度为O(n)。

3.顺序存储结构的优缺点

优点:

  • 无需为表示表中元素之间的逻辑关系而增加额外的存储空间
  • 可以快速地存取表中任意位置的元素

缺点:

  • 插入和删除操作需要移动大量元素
  • 当线性表长度变化较大时,难以确定存储空间的容量
  • 造成存储空间的“碎片”

三、链式存储结构

1.定义

链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素,这组存储单元可以是连续的,也可以是不连续的。为了表示每个数据元素 ai 与其直接后记数据元素 ai+1 之间的逻辑关系,对于数据元素ai来说,除了存储本身的信息之外,还需要存储一个指示其直接后继的信息。
通常把存储数据元素信息的域称为数据域,把存储直接后继位置的域称为指针域。指针域中存储的信息称作指针。这两部分信息组成数据元素ai的存储影像,称为结点
n个结点链接成一个链表,称为线性表的链式存储结构。因为此链表的每个结点中只包含一个指针域,所以叫单链表。链表中第一个结点的存储位置叫做头指针,最后一个结点的指针为空。为了更方便对链表进行操作,会在单链表的第一个结点前附设一个结点,称为头节点。头节点的数据域可以不储存任何数据信息,也可以存储线性表的长度等附加信息。

头指针与头结点的异同

头指针 头节点
头指针是指链表指向第一个结点的指针,若链表有头节点,则是指向头节点的指针 头节点是为了操作的统一和方便而设立的,放在第一元素的结点之前,其数据域一般无意义
头指针具有标识作用,所以常用头指针冠以链表的名字 有了头节点,对在第一元素结点前插入和删除第一结点,其操作与其他结点的操作就统一了
无论链表是否为空,头指针均不为空。头指针是链表的必要元素。 头节点不一定是链表必需元素

2.单链表的各种基本操作

读取元素

获取链表第 i 个数据的算法思路:

  • 声明一个指针p指向链表第一个结点,初始化 j 从1开始;
  • 当 j < i 时,就遍历链表,让p的指针向后移动,不i段指向下一结点,j 累加1;
  • 若到链表末尾p为空,则说明第 i 个结点不存在;
  • 否则查找成功,返回结点p的数据

插入元素

单链表第 i 个数据插入结点的算法思路:

  • 声明一指针p指向链表头节点,初始化 j 从1开始;
  • 当 j < i 时,就遍历链表,让p的指针向后移动,不i段指向下一结点,j 累加1;
  • 若到链表末尾p为空,则说明第 i 个结点不存在;
  • 否则查找成功,在系统中生成一个空结点s;
  • 将数据元素e赋值给s->data;
  • 单链表的插入标准语句s->next=p->next; p->next=s;
  • 返回成功。

删除元素

单链表第 i 个数据删除结点的算法思路:

  • 声明一指针p指向链表头节点,初始化 j 从1开始;
  • 当 j < i 时,就遍历链表,让p的指针向后移动,不i段指向下一结点,j 累加1;
  • 若到链表末尾p为空,则说明第 i 个结点不存在;
  • 否则查找成功,将欲删除的结点p->next赋值给q;
  • 单链表的删除标准语句p->next=q->next;
  • 将q结点中的数据赋值给e,作为返回;
  • 释放q结点;
  • 返回成功。

整表创建

单链表整表创建的算法思路(头插法):

  • 声明一指针p和计数器变量 j;
  • 初始化一空链表L;
  • 让L的头节点指针指向NULL,即建立一个带头结点的单链表;
  • 循环:
    1.生成一新节点赋值给p;
    2.随机生成一数字赋值给p的数据域p->data;
    3.将p插入到头节点与前一新结点之间

整表删除

单链表整表删除的算法思路:

  • 声明一指针p和 q;
  • 将第一个结点赋值给p;
  • 循环:
    1.将下一结点赋值给p
    2.释放p
    3.将q赋值给p

3.单链表结构与顺序存储结构的比较

比较项目 单链表结构 顺序存储结构
存储分配方式 采用链式存储结构,用一组任意的存储单元存放线性表的元素 用一段连续存储单元依次存储线性表的数据元素
时间性能 查找 :O(n) 插入和删除:单链表在找出位置的指针后,插入和删除的时间复杂度仅为O(1) 查找:O(1) 插入和删除:顺序存储结构需要平均移动表长一半的元素,时间复杂度为O(n)
空间性能 不需要分配存储空间,只要有就可以分配,元素个数也不受限制 需要预分配存储空间,分大了造成存储空间的浪费,分小了易发生上溢

总结

  • 若线性表需要频繁查找,很少进行插入和删除操作,宜采用顺序存储结构。

  • 当线性表中的元素个数变化较大或者根本不知道有多大时,最好采用单链表结构。

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