04-线性表

1.线性表的定义及逻辑结构

线性表(LinearList)是由n(n$ \geq 0 ) 个 属 于 同 一 个 数 据 对 象 的 数 据 元 素 ( 节 点 ) 0)个属于同一个数据对象的数据元素(节点) 0)()a_1,a_2,a_3,…,a_n$组成的有限序列。

线性表中每个元素必须具有相同的结构(即拥有相同的数据项)。线性表是线性结构中最常用而又最简单的一种数据结构。

线性表中每个数据元素其实可以包含若干个数据项,例如,使用 a i a_i ai来代表线性表中的第i个元素,其中 a i a_i ai元素可以包含若干个数据项。

  • 线性表中包含的数据元素个数n被称为表的长度,当线性表的长度为0是该表也被称为空表。
  • 当n>0时,表可以表示为( a 1 , a 2 , a 3 , . . . , a n a_1,a_2,a_3,...,a_n a1,a2,a3,...,an)

对于一个非空,有限的线性表而言,它总具有如下特征。

  • 总存在唯一的“第一个”数据元素。
  • 总存在唯一的“最后一个”数据元素。
  • 除第一个数据元素外,集合中的每一个数据元素都只有一个前驱的数据元素。
  • 除了最后一个数据元素外,集合中的每个数据元素都只有一个后继的数据元素。

同一个线性表中的数据元素必定具有相同特性,即它们都属于同一个数据对象。

前驱和后继

数据结构中,一组数据中的每个个体成为“数据元素”(简称“元素”)。

  • 某一元素的左侧相邻元素称为“直接前驱”,位于此元素左侧的所有元素都统称为“前驱元素”。
  • 某一元素的右侧相邻元素称为“直接后驱”,位于此元素右侧的所有元素都统称为“后驱元素”。

2.线性表的基本操作

如果需要实现一个线性表,程序首先需要确定该线性表的每个数据元素。接下来,应该为该线性表实现如下基本操作。

  • 初始化:通常是一个构造器,用于创建一个空的线性表
  • 返回线性表的长度:该方法用于返回线性表中的数据元素
  • 获取指定索引处的元素:根据索引返回线性表的数据元素
  • 按值查找数据元素的位置:如果线性表中存在一个或多个与查找值相等的数据元素,那么该方法返回一个搜索到的值相等的数据元素的索引,否则返回-1.
  • 直接插入数据元素:向线性表的头部插入一个数据元素,线性表长度+1;
  • 向指定位置插入数据元素:向线性表的指定索引处插入一个数据元素,线性表长度+1.
  • 直接删除数据元素:删除线性表头部的数据元素,线性表长度-1.
  • 删除线性表中指定位置的数据元素:删除线性表中指定索引处的数据元素,线性表长度-1.
  • 判断线性表是否为空:该方法判断线性表是否为空,如果线性表为空,则返回true,否则返回false
  • 清空线性表:将线性表清空
    在这里插入图片描述

1.确定元素item在长度为n的顺序表A中的位置

在这里插入图片描述

2.在长度为n的顺序表A的第i个位置上插入一个新的数据元素item

在这里插入图片描述

3.删除长度为n的顺序表A的第i个数据元素

在这里插入图片描述

注:进行某些操作(如对线性表进行插入或者删除操作)时,在某种存储结构下,会引起一系列元素的移动,降低操作效率,尤其是当线性表的长度很大时,这种移动可能比较突出。

3.线性表和数组的关系

数组

数组就是相同数据类型的元素按一定顺序排列的集合。本质:物理上存储在一组联系的地址上,也就是数据结构中的顺序存储物理结构

数组分为静态数组和动态数组,在定义数组时,首先要确定数组的大小。

静态数组在编译时就需要确定数组的大小,所以,为了防止内存溢出,我们尽量将数组定义的大一些,但是这样太过浪费内存。

动态数组则不同,它不需要在编译时就确定大小,它的大小在程序运行过程中确定,所以可以根据程序需要而灵活的分配数组的大小,相比静态数组,它更“灵活”、“自由”。但是动态数组需要进行显式的内存释放。

线性表

线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的。本质:线性表是数据结构中的逻辑结构。线性表可以通过数组(顺序存储结构)存储,也可以通过链式存储

线性表根据存储结构的不同可以分为顺序表和链表。其中,顺序表为顺序存储的线性表,即用数组描述的线性表就是顺序表;链表为链式存储的线性表。

链表可以根据描述方式的不同分为静态链表和动态链表。通过指针对链表进行描述的称为动态链表,如我们常说的单链表,循环链表等;通过数组对链表进行描述的称为静态链表,主要为了解决没有指针或者不用指针的情况下具备链表插入删除操作便捷的特性。

注意

看到很多人直接将顺序表等同于动态数组,认为实现了数组长度可变,数据可删减,但这样做容易造成概念混淆。我们可以通过数组实现顺序表,但动态数组的概念并不是实现数组长度可变,而是通过new操作符或malloc函数实现运行时内存的动态分配。

4.线性表的存储结构

1.顺序存储结构

定义

线性表的顺序存储结构是指用一组地址连续的存储单元依次存放线性表的元素。当程序采用顺序存储结构来实现线性表时,线性表中相邻元素的两个元素 a i a_i ai a i + 1 a_i+1 ai+1对应的存储地址 l o c ( a i ) loc(a_i) loc(ai) l o c ( a i + 1 ) loc(a_i+1) loc(ai+1)也是相邻的。

换句话说,顺序结构线性表中数据元素的物理关系和逻辑关系是一致的。

顺序存储结构比较适合于线性表的长度不经常发生变化,或者只需要在顺序存取设备上做批处理的场合。

优点

  • 构造原理简单、直观、易理解
  • 元素的存储地址可以通过一个简单的解析式计算出来。是一种随机存储结构,存储速度快。
  • 由于只需存放数据元素本身的信息,而无其他空间开销,相对链式存储结构而言,存储空间开销小。

缺点

  • 存储分配需要事先进行
  • 需要一篇地址连续的存储空间
  • 基本操作(如插入、删除)的时间效率低–O(n)

2.链式存储结构

在这里插入图片描述

定义

链式存储结构的线性表(简称为链表)将采用一组地址任意的存储单元存放线性表中的数据元素。链式存储结构的线性表不会按线性的逻辑顺序来保存数据元素,他需要在每个数据元素里保存一个引用下一个数据元素的引用(或者叫指针)。

优点

  • 存储空间动态分配,可以根据实际需要使用
  • 不需要地址连续的存储空间
  • 插入/删除操作只需要修改指针实现,不必移动数据元素,操作的时间效率较高

无论位于链表何处,无论链表的长度如何,插入和删除操作的时间都是O(1)

缺点

  • 每个链接点需要设置指针域(存储密度小)
  • 是一种非随机存储结构,查找、定位等操作要通过顺序扫描链表实现,时间效率较低

1.单向链表

在链表结构中,每个节点仅存储本身需要存储的数据和下一个节点地址的这种链表结构,我们称为单链表结构,其示意图如下:
在这里插入图片描述

如图所示,在单链表中的每个节点中,除了数据区域外,还有一个区域存储了当前节点的下一节点的地址,我们把这个记录下个结点地址的指针或引用叫作后继指针或引用Next。

2.循环链表

循环链表是一种特殊的单链表,特殊之处在于,我们在单链表中,尾节点的后继指针或者引用不是指向一个具体的节点,而是指向一个空地址NULL,表示这就是最后一个节点。而将单链表的尾节点从指向空地址NULL调整为指向头结点Head,就形成了循环链表。
在这里插入图片描述

3.双向链表

单向链表是单向的,只有一个后继指针或者引用Next指向后面的节点,而双向链表,指的是一个链表结构,它支持两个方向,每个节点不止只有一个后继指针或者引用Next指向后继节点,还有一个前驱指针或者引用Prev指向前面的节点。
在这里插入图片描述

从图中可以得知,双向链表需要额外的空间来存储后继节点和前驱节点的地址,所以,存储同样多的数据,双向链表要比单向链表需要的存储空间要多。虽然两个指针或者引用比较浪费存储空间,但可以支持双向遍历,这样也带来了双向链表操作的灵活性。

1.双向链表的插入

在这里插入图片描述

在这里插入图片描述

2.双向链表的删除

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值