2.3_线性表的链式存储结构_单链表
【线性表的链式存储结构的特点】
用一组任意的存储单元存储线性表的数据元素,这组存储单元可以是连续的,也可以是不连续的。这就意味着,这些数据元素可以存储在内存未被占用的任意位置。
现在的链式结构,除了要存储数据元素信息之外,还要存储后继元素的存储地址。
【几个重要的名词】
为了表示每个数据元素ai与其后继数据元素ai+1之间的逻辑关系,对数据元素ai来说,除了存储其本身的信息之外,还需要存储一个指示其后继元素的信息(即直接后继的存储位置)。
数据域:存储数据元素信息的域。
指针域:存储直接后继位置的域。(指针或链:指针域中存储的信息)
结点:存放数据元素的数据域+存放后继结点地址的指针域组成。
链表:n个节点(ai的存储映像)链接成一个链表,即为线性表(a1,a2,....,an)的链式存储结构,因为此链表的每个节点都包含一个指针域,所以叫做单链表。单链表正是通过每个节点的指针域将线性表的数据元素按其逻辑次序链接在一起。
头指针:链表中的第一个节点的存储位置叫做头指针。(整个链表的存取必须从头指针开始进行,之后的每一个结点,起始就是上一个结点的后继指针指向的位置)。
线性链表的最后一个结点指针为空,即NULL。
头节点:为了更方便地对链表进行操作,会在单链表的第一个节点前附设一个结点,称为头结点。头结点的数据域可以不存储任何信息,也可以存储例如线性表的长度等附加信息,头结点的指针域存储指向第一个节点的指针。
[ 没有头结点的情况,头指针直接指向第一个结点a1 ]
[ 有头结点的情况下,头指针直接指向头结点,头结点的指针指向第一个结点 ]
[ 空链表的情况 ]
【头结点和头指针的区别】
[ 头指针 ]
1.头指针指链表指向第一个结点的指针,若链表有头结点,则是指向头结点的指针。
2.头指针有标识作用,所以常用指针冠以链表的名字。
3.无论链表是否为空,头指针均不为空。头指针是链表的必要元素。
[ 头结点 ]
1.头结点是为了操作的统一和方便而设立的,放在第一元素的结点之前,其数据域一般无意义(也可以存放链表的长度。)
2.有了头结点,对在第一元素结点前插入结点和删除第一节点,其操作与其他结点的操作就统一了。
3.头结点不一定是链表必需要素。
【单链表:读取第i个数据的思路】
1.声明一个结点P指向链表的第一个结点,初始化j从1开始。
2.声明 j<i 时,就遍历链表,让P的指针向后移动,不断指向下一结点,j 累加1。
3.若到链表末尾P为空,则说明第 i 个元素不存在。
4.否则查找成功,返回结点P的数据。
注意:算法时间复杂度为O(n)。
【单链表:在第i个位置插入结点的思路】
1.声明一个结点P指向链表的第一个节点,初始化 j 从1开始。
2.当 j<i 时,就遍历链表,让P的指针向后移动,不断指向下一结点,j 累加 1。
3.若到链表的末尾为空,则说明第i个元素不存在。
4.否则查找成功,在系统中生成一个空节点s。
5.将数据元素e 赋值给s->data。(C语言结构体)
6.单链表的插入标准语句为
s->next=p->next;
p->next=s;
7.返回成功。
【单链表:删除第i个数据的思路】
1.声明一结点P指向链表的第一个结点,初始化j从1开始。
2.当 j<i 时,就遍历链表,让P的指针向后移动,不断指向下一个结点,j 累加1。
3.若到链表末尾P为空,则说明第 i 个元素不存在。
4.否则查找成功,将欲删除的结点P->next赋值给q。
5.单链表删除标准语句:p->next=q->next; 。
6.将q结点中的数据赋值给e,作为返回。
7.释放q结点。
8.返回成功。
【单链表:整表创建的思路】
1.声明一个结点P和计数变量 i 。
2.初始化一个空链表 L 。
3.让L的头结点的指针指向NULL,即建立一个带头结点的单链表。
4.循环以下步骤:
4.1.生成一新结点赋值给P。
4.2.随机生成一数字赋值给P的数据域p->data。(这里当然是我们需要存储的数据,用随机数模拟)
4.3.将P插入到头结点与前一新结点之间。
【单链表:整表删除的思路】
1.声明一结点P和q。
2.将第一个结点赋值给P。
3.循环以下步骤:
3.1. 将下一结点赋值给q。
3.2. 释放P。
3.3. 将q赋值给P。
【单链表结构对比顺序存储结构】
[ 存储分配方式上 ]
1.顺序存储结构用一段连续的存储单元依次存储线性表的数据元素。
2.单链表采用链式存储结构,用一组任意的存储单元存放线性表的元素。
[ 时间性能 ]
1.查找:
顺序存储结构:O(1)
单链表:O(n)
2.插入和删除:
顺序存储结构:需要平均移动表长一半的元素,时间为O(n)
单链表:在找出某位置的指针后,插入和删除时间为O(1)
[ 空间性能 ]
顺序存储结构:需要预先分配存储空间,分大了浪费空间,分小了易发生溢出。
单链表:不需要分配存储空间,只要有就可以分配,元素个数也不受限制。
【结论】
1.若线性表需要 频繁查找、较少插入和删除时-------->采用顺序存储结构。
2.若线性表需要 频繁插入和删除、较少查找时-------->采用单链表结构。
3.当线性表中的元素个数变化较大或者根本不知道有多大时------>采用单链表结构。