第二章 线性表

第二章 线性表

2.1 线性表的定义

线性表是具有相同数据类型的n个数据序列的有限序列,其表示为:

L = (a1, a2, a3…, an)

线性表特性如下:

  • 表中元素个数有限
  • 表中元素具有逻辑上的顺序性,表中元素有其先后次序
  • 表中元素数据类型相同,每个元素占的存储空间相同
  • 表中元素具有抽象性,也就是只需要讨论元素之间关系,而不需要考虑元素表示什么内容

2.2 线性表的顺序表示:顺序表

顺序表的定义

线性表的顺序存储称为顺序表。它是用一组地址连续的存储单元一次存储线性表中的数据元素,从而使得逻辑上相邻的两个元素在物理位置上也相邻。因此,顺序表的特点是表中元素的逻辑顺序与其物理顺序相同

一维数组可以是静态分配的,也可以是动态分配的。在静态分配中,由于数组大小事先固定,一旦空间占满再加入新数据就会产生溢出,导致程序崩溃。而动态分配在数据空间占满时会另外开辟新的更大的内存空间,从而将原来的数据转移到新的内存空间中,并回收原来的内存空间。

  • 顺序表的主要特点是随机访问,指的是顺序表通过首地址和元素序号可以在时间O(1)内找到指定的元素。指的是顺序表可以不经过前驱元素,直接访问顺序表中的任意元素
  • 顺序表的存储密度高,因为每个节点只存储数据元素
  • 顺序表逻辑上相邻的元素物理上也相邻,因此插入和删除操作需要移动大量元素

顺序表上的基本操作

  1. 插入操作

最好情况:在表尾插入,不需要后移元素,时间复杂度O(1)

最坏情况:在表头插入,元素后移语句执行n次,时间复杂度O(n)

平均情况:n/2

  1. 删除操作

最好情况:删除表尾元素,不需要移动元素,时间复杂度O(1)

最坏情况:删除表头元素,元素前移语句执行n次,时间复杂度O(n)

平均情况:(n-1)/2

  1. 按值查找

最好情况:所查找元素在表头,只需要比较一次,时间复杂度O(1)

最坏情况:所查元素在表尾(或不存在),要比较n次,时间复杂度O(n)

平均情况:(n+1)/2

2.3 线性表的链式表示

链式存储线性表时,不需要使用地址连续的存储单元,也就是不要求逻辑上相邻的元素在物理上也相邻,而是采用链建立起数据之间的逻辑关系,因此插入和删除不需要移动元素(后续会解释)

2.3.1 单链表的定义

线性表的链式存储又称为单链表,它是通过一组任意的存储单元来存储线性表中的数据元素的,为了建立数据元素之间的线性关系,每个链表节点除了存放元素自身信息之外,还需要存放一个指向后续节点的指针。单链表节点结构如下:

数据域data指针域(下个节点的地址next)

可以这样理解单链表的数据间的逻辑关系,假设你是一个问卷调查员,但是你只有第一家调查对象的地址,而去了第一家调查对象后,他会告诉你第二家的地址;去到第二家后,第二家会告诉你第三家的地址…以此类推

单链表可以解决顺序表需要大量连续存储单元的缺点,但是单链表附加指针域,其空间利用率不如顺序表。而单链表的元素离散存储在存储空间中,因此想要查询第n个元素必须要先经过前n-1个元素,因此,单链表是非随机存取的存储结构

可以通过头指针来标识一个单链表,头指针指向单链表的第一个节点,正如上面例子的第一家的地址一样。而为了操作上的方便,在单链表的第一个节点之前会附加一个头节点。头节点的数据与可以不存储信息,也可以存储链表长度等信息。

头节点的两个优势在于:

  • 由于第一个数据节点的位置被存放在头节点的指针域中,因此在链表的第一个位置上的操作和在表的其他位置上的操作一致,无需进行特殊化处理。
  • 无论链表是否为空,其头指针都指向了头节点,因此空表和非空表的操作也得到了统一。

2.3.2 单链表上基本操作的实现

  1. 头插法创建单链表
  2. 尾插法创建单链表
  3. 按序号查找节点值
  4. 按值查找表节点
  5. 插入节点删除节点操作
  6. 求表长

2.3.3 双链表

单链表中只有一个指向后继的指针,使得单链表只能从头节点依次顺序地向后遍历。要访问某一个节点的前驱节点只能从头开始遍历,导致出现了一定的时间浪费。为了克服上述缺点,引入了双链表,在双链表的节点中有两个指针:指向该节点前驱的prior和指向该节点后继的next。

2.3.4 循环链表

循环单链表和单链表的区别在于,表中的最后一个节点的指针不是NULL,而是改为指向头节点。

1.循环单链表

2.循环双链表

2.3.5 静态链表

静态链表借助数组来描述线性表的链式储存结构,结点也有数据域和指针域。但是不同的是,这里的指针式节点的相对地址(数组的下标),又称游标。和顺序表一样,静态链表也要预先分配一块连续的内存空间。

2.3.6 顺序表和链表的比较

  1. 存取(读写)方式

顺序表可以顺序存取,也可以随机存取,链表只能发从表头顺序存取元素

  1. 逻辑结构和物理结构

采用顺序存取的时候,逻辑上相邻的元素物理存储位置也相邻。采用链式存储的时候,逻辑上相邻的元素物理存储位置可能不相邻

  1. 查找、插入和删除操作

对于按值查找,顺序表无序的时候,两者时间复杂度都是O(n)。顺序表有序的时候,使用折半查找时间复杂度为O(log2n)

  1. 空间分配

顺序表在静态存储分配的情形下,一旦储存空间满后再加入新元素,则会导致内存溢出;动态存储的顺序表虽然可以扩展大小,但是需要移动大量的元素,导致操作效率低下。链式存储的节点空间只在需要时申请分配,因此操作更灵活高效

什么时候使用顺序表?什么时候使用链表?

  1. 基于存储的考虑

难以估计线性表的长度或者规模的时候,不宜采用顺序表

  1. 基于运算的考虑

如果经常需要按照元素序号来访问的话,建议使用顺序表(因为顺序表是随机存储的)。在顺序表中执行插入、删除操作的时候比较麻烦,如果需要频繁插入或删除,建议使用链式存储,

  1. 基于环境考虑

顺序表实现更加容易

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值