数据结构——线性表List(详细知识点总结)

目录

一、了解线性表

二、线性表的顺序存储结构

三、线性表的链式存储结构

1、单链表

头插法、尾插法:

2、双链表

3、循环链表

4、静态链表

四、顺序表和链表的比较


线性表作为数据结构中比较重要的一种,具有操作效率高、内存利用率高、结构简单、使用方便等特点,今天我们一起交流一下单向线性表的头插法和尾插法的区别及优缺点

一、了解线性表

线性表(List):零个或者多个数据元素的有限序列。如:

L=(a1​,a2,​,⋯,ai​,ai+1​,⋯,an​)

线性表的数据集合为(a1,a2,…,an),除第一个元素a1外,每一个元素有且只有一个直接前驱元素,除了最后一个元素an外,每一个元素有且只有一个直接后继元素。数据元素之间的关系是一对一的关系。

线性表的特点:

表中元素的个数有限。

表中元素具有逻辑上的顺序性,表中元素有其先后次序。

表中元素都是数据元素,每个元素都是单个元素。

表中元素的数据类型都相同,这意味着每个元素占有相同大小的存储空间。

表中元素具有抽象性,即仅讨论元素间的逻辑关系,而不考虑元素究竟表示什么内容。

线性表有顺序存储和链式存储两种存储方式。

二、线性表的顺序存储结构

顺序表定义:用一组地址连续的存储单元依次存储线性表的数据元素,从而使得逻辑上相邻的两个元素在物理位置上也相邻,那么这种存储结构的线性表被我们称为顺序表。

顺序表在逻辑上相邻的数据元素在物理层次上也相邻。所以我们只要确定了存储线性表的起始位置,线性表中的每一个元素都能够随机存取。

随机存取:线性表的顺序存储结构是一种随机存取的储存结构,因为高级语言中的数组类型也是有随机存取的特性,所以通常我们都使用数组来描述数据结构中的顺序储存结构,用动态分配的一维数组表示线性表。

内存分配方式:一维数组的内存分配方式有静态分配和动态分配。在静态分配时,由于数组的大小和空间事先已经固定,一旦空间占满,再加入新的数据就会产生溢出,进而导致程序崩溃。 在动态分配时,存储数组的空间是在程序执行过程中通过动态存储分配语句分配的,一旦数据空间占满,就另外开辟一块更大的存储空间,从而替换原来的存储空间,达到扩充存储数组空间的目的,而不需要为线性表一次性地划分所有空间。

顺序表时间复杂度:顺序表逻辑上相邻的元素物理上也相邻,所以线性表的顺序存储结果在读、存数据是的时间复杂度是O(1),而插入和删除操作却需要移动大量元素,他的时间复杂度是O(n)。

顺序表的优缺点:
优点:无须为表中元素之间的逻辑关系而增加额外的存储空间;可以快速的存取表中任一位置的元素。
缺点:插入和删除操作需要移动大量元素;当线性表长度较大时,难以确定存储空间的容量;造成存储空间的“碎片”。

三、线性表的链式存储结构

1、单链表

定义:通过一组任意的存储单元来存储线性表中的数据元素。为了建立数据元素之间的线性关系,对每个链表结点,除存放元素自身的信息外,还需要存放一个指向其后继的指针。

对于ai而言,他除了存储其本身的信息之外,还需要存储一个指示其直接后继的信息(即直接后继ai+1的存储位置)。我们把存储数据元素信息的域称为数据域,把存储直接后继位置的域称为指针域。指针域中存储的信息称做指针或链。这两部分信息组成数据元素ai的存储映像,称为结点(Node)。n个结点(ai的存储映像)链结成一个链表,即为线性表(a1, a2, …, an)的链式存储结构,因为此链表的每个结点中只包含一个指针域,所以叫做单链表。把链表中第一个结点的存储位置叫做头指针。有时为了方便对链表进行操作,会在单链表的第一个结点前附设一个节点,称为头结点,此时头指针指向的结点就是头结点。

头插法、尾插法:

因为每个元素都包含一个指向下一元素的指针,所以新增、删除、修改起来非常简单迅速,就像火车一样,一节一节的,想增加就加上一节就成,非常方便。

那么在插入的时候却有两种方法,头插和尾插。顾名思义,头插就是将新元素插在链表头部,尾插就是将新元素插在链表尾部。他们的区别在于,如果是头插法的话,那么新元素直接作为头结点,next指针指向旧的头结点即可,非常方便迅速效率高。如果是尾插法的话,添加新元素时需要遍历旧链表,直到某个节点的next指针为空,说明这个节点是尾节点,修改这个尾节点的next指针为新添加的元素即可

特点:

头插法:
插入速度快(不需要遍历旧链表);
头结点每次插入都会变化,头结点永远是最新的元素;
遍历时是按照插入相反的顺序进行;
由于头结点不断在变化,所以需要额外的维护头结点的引用,否则找不到头结点,链表就废了。

尾插法:
插入速度慢(需要遍历旧链表到最后一个元素);
头结点永远固定不变;
遍历时是按照插入相同的顺序进行。

另外除此之外,也有人从业务角度讨论过两种的区别。现在很多网站或者系统都有一个“最近使用”之类的功能,这种可以考虑用头插法实现。

当你使用一个功能的时候,就使用头插法插入一个,查看最近使用的时候直接遍历线性表,即可得到按照最近使用排好序的内容

时间复杂度:头插法、尾插法、按序号查找结点、按值查找结点、插入操作、删除操作都是O ( n )

2、双链表

定义:是在单链表的每个结点中,再设置一个指向其前驱结点的prior指针。所以在双向链表中的结点都有两个指针域,一个指向直接后继,另一个指向直接前驱。

因此双链表中的按值查找和按位查找的操作与单链表的相同。但双链表在插入和删除操作的实现上,与单链表有着较大的不同。 这是因为"链”变化时也需要对prior指针做出修改,其关键是保证在修改的过程中不断链。此外,双链表可以很方便地找到其前驱结点,因此,插入、删除操作的时间复杂度仅为0(1)。

双链表的插入和删除要同时注意前驱和后驱指针的修改。

插入操作:

//第一步:把p赋值给s的前驱
s->prior = p;
//第二步:把p->next赋值给s的后继
p->next = p->next
//第三步:把s赋值给p->next的前驱
p->next->prior = s;
//第四步:把s赋值给p的后继
p->next = s;

删除操作:

//第一步
p->next = q->next;
//第二步
q->next->prior = p;
free(q);

3、循环链表

定义:将单链表中终端节点的指针端由空指针改为指向头结点,就使整个单链表形成一个环,这种头尾相接的单链表称为单循环链表,简称循环链表。

从图中可以看到,终端节点用尾指针rear指示,则查找终端节点是O(1),而开始节点,其实就是rear->next->next,其时间复杂度也是O(1)。

当我们将两个链表合成一个的时候只需要让他们的尾指针指向对方的头结点即可,如图中rearA和rearB所示:

//第一步:保存A的头结点
p = rearA->next;
//第二步:将本是指向B表的第一个节点(不是头结点)赋值给rearA->next
rearA->next = rearB->next->next;
//第三步:将原A表的头结点赋值给rearB->next
rearB->next=p;
//释放p
free(p);

4、静态链表

定义:使用数组连描述指针,首先我们让数组的元素都是由两个数据域组成,data和cur。数据域data,用来存放数据元素。这里与前面所讲的链表中的指针不同的是,这里的next指针是结点的相对地址(数组下标),又称游标cur,是存放该元素的后继在数组中的下标。 和顺序表一样,静态链表也要预先分配一块连续的内存空间。静态链表以next==-l作为其结束的标志。静态链表的插入、删除操作与动态链表的相同,只需要修改指针,而不需要移动元素。

四、顺序表和链表的比较

存取方式:顺序表可以顺序存取,也可以随机存取,链表只能从表头顺序存取元素。
逻辑结构和物理结构:采用顺序存储时,逻辑上相邻的元素,对应的物理存储位置也相邻。而采用链式存储时,逻辑上相邻的元素,物理存储位置不一定相邻,对应的逻辑关系是通过指针链接来表示的。
查找、插入和删除:对于按值查找,顺序表无序时,两者的时间复杂度均为O(n);顺序表有序时,可采用折半查找,此时的时间复杂度为O(log2n)。

对于按序号查找,顺序表支持随机访问,时间复杂度仅为O(1),而链表的平均时间复杂度为O(n)。顺序表的插入、删除操作,平均需要移动半个表长的元素,时间复杂度为O(n)。链表的插入、删除操作,只需修改相关结点的指针域即可。

空间分配:顺序存储在静态存储分配情形下,一旦存储空间装满就不能扩充,若再加入新元素,则会出现内存溢出,因此需要预先分配足够大的存储空间。预先分配过大,可能会导致顺序表后部大量闲置;预先分配过小,又会造成溢出。动态存储分配虽然存储空间可以扩充,但需要移动大量元素,导致操作效率降低,而且若内存中没有更大块的连续存储空间,则会导致分配失败。链式存储的结点空间只在需要时申请分配,只要内存有空间就可以分配,操作灵活、高效。

参考链接:https://zhuanlan.zhihu.com/p/361636579

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值