Ch2.3线性表 -链式存储 - 作业答案

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
10
head bat cat eat … mat ^
单链表是由表头唯一确定,因此单链表可以用头 指针的名字来命名。 例如:若头指针名是head,则把链表称为表head。
11
单链表的定义
上例中, 用C语言描述的单链表如下: Typedef char datatype; Typedef struct listnode{ datatype data; struct node *next; }listnode;
head=p; ch=getchar( ); } return (head); }
16
2、尾插法建表 头插法建立链表虽然算法简单,但 生成的链表中结点的次序和输入的顺序相反。 若希望二者次序一致,可采用尾插法建表。 该方法是将新结点插入到当前链表的表尾上, 为此必须增加一个尾指针r,使其始终指向当 前链表的尾结点。例:
p
p
p
p
p
first
a1
a2
ai
查找成功
an ∧
查找失败
核心操作(关键操作):工作指针后移。 核心操作(关键操作):工作指针后移。从头结点 ):工作指针后移 或开始结点)出发, (或开始结点)出发,通过工作指针的反复后移而将 整个单链表“审视”一遍的方法称为扫描 或遍历) 扫描( 整个单链表“审视”一遍的方法称为扫描(或遍历) 30 。
14
算法:
void createlistf(linklist &head) { char ch; listnode *p; head=null; ch=getchar( ); while (ch!=‵\n′){ p=(listnode*)malloc(sizeof(listnode));
15
p–>data=ch; p–>next=head;
21
2.3 线性表的链接存储结构及实现
单链表
0200
头指针:指向第一个结点的地址。 头指针:指向第一个结点的地址。 尾标志:终端结点的指针域为空。 尾标志:终端结点的指针域为空。 空表 first=NULL 非空表 first a 1 a2 an ∧
0208
0300
0325
… a2 0325 a1 0200 … a4 ∧ … a3 0300 …

an
c
空闲
长度
Loc(ai) 如何求得任意元素的存储地址? 如何求得任意元素的存储地址?
5
2.3 线性表的链式表示和实现
线性表的顺序表示的特点是用物理位置上的 邻接关系来表示结点间的逻辑关系,这一 特点使我们可以随机存取表中的任一结点, 但它也使得插入和删除操作会移动大量的 结点.为避免大量结点的移动,我们介绍线 性表的另一种存储方式,链式存储结构, 简称为链表(Linked List)。
27
上述算法里动态申请新结点空间时未加错误处理, 可作下列处理: p=(listnode*)malloc(sizeof(listnode)) if(p==NULL) error(〝No space for node can be obtained〞); return ERROR; 以上算法的时间复杂度均为O(n)。
23
2.3 线性表的链接存储结构及实现
单链表
头结点: 头结点:在单链表的第以一个元素结点之前附设一个 类型相同的结点,以便空表和非空表处理统一。 类型相同的结点,以便空表和非空表处理统一。 空表 first 非空表 first a1 a2 an ∧
24

如果我们在链表的开始结点之前附加一个 结点,并称它为头结点,那么会带来以下两个 优点: a、由于开始结点的位置被存放在头结点 的指针域中,所以在链表的第一个位置上的操 作就和在表的其它位置上的操作一致,无需进 行特殊处理; b、无论链表是否为空,其头指针是指向头结 点的非空指针(空表中头结点的指针域为空), 因此空表和非空表的处理也就统一了。 其算法如下: 25
20
引入头节点
单链表
什么是存储结构? 什么是存储结构? 重点在数据元素之间的逻辑关系的 表示,所以,将实际存储地址抽象。 表示,所以,将实际存储地址抽象。 空表 first=NULL 非空表 first a 1 a2 an ∧
0325 0200 0208
0300
… a2 0325 a1 0200 … a4 ∧ … a3 0300 …
18
if(head=NULL) head=p; else r–>next=p; r=p; } if (r!=NULL) r–>next=NULL; return(head); }
19
说明: 说明: 第一个生成的结点是开始结点,将开始结点插入 到空表中,是在当前链表的第一个位置上插入,该位 置上的插入操作和链表中其它位置上的插入操作处理 是不一样的,原因是开始结点的位置是存放在头指针 (指针变量)中,而其余结点的位置是在其前趋结点 的指针域中。算法中的第一个if语句就是用来对第一 个位置上的插入操作做特殊处理。 算法中的第二个if语句的作用是为了分别 处理空表和非空表两种不同的情况,若读入的第一个 字符就是结束标志符,则链表head是空表,尾指针r 亦为空,结点*r不存在;否则链表head非空,最后一 个尾结点*r是终端结点,应将其指针域置空。
28
二、查找运算
1、按序号查找 在链表中,即使知道被访问结点的序号i, 也不能象顺序表中那样直接按序号i访问结点, 而只能从链表的头指针出发,顺链域next逐个 结点往下搜索,直到搜索到第i个结点为止。 因此,链表不是随机存取结构,而是顺序存储 结构。
29
单链表的实现——按号查找 按号查找 单链表的实现
Status createlistr1(linklist &head) { char ch; head=(linklist)malloc(sizeof(listnode)); listnode *p,*r
26
r=head;
while((ch=getchar( ))!=‵\n′{ p=(listnode*)malloc(sizeof(listnode)); p–>data=ch; r–>next=p; r=p; } r–>next=NULL; return(head); }
例题:设单链表的长度为n,要查找表中第i个结点, 仅当1≦i≦n时,i的值是合法的。但有时需要找 头结点的位置,故我们将头结点看做是第0 个结 点,其算法如下:
31
void getnode(linklist head , int i) { int j; listnode * p; p=head;j=0; while(p–>next && j<i){ p=p–>next; j++; } if (i==j) return p;
如何实现顺序表的内存分配? 如何实现顺序表的内存分配?
顺序表
一维数组
4
2.2 线性表的顺序存储结构及实现
一般情况下, 的顺序存储: 一般情况下,(a1,a2,…, ai-1,ai , …, an)的顺序存储: 的顺序存储
0 … i-2 i-1 … n-1 Max-1
a1
Loc(a1)

ai-1
ai
…… 110 …… 130 135 …… 160 头指针 head 165 170 165 …… 200 205 ……
…… … hat ……. cat eat …. mat bat fat …… jat lat …… …… 200 …… 135 170 …… Null 130 110 …… 205 160 ……
函数malloc分配了一个类型为listnode的结 点变量的空间(空间大小为listnode这种数据 类型所占的字节长度),并将其首地址放入指 针变量p中。一旦p所指的结点变量不再需要 了,又可通过标准函数 free(p) 释放所指的结点变量空间。
13
一、建立单链表
假设线性表中结点的数据类型是字符,我们逐个 输入这些字符型的结点,并以换行符‘\n’为 输入结束标记。动态地建立单链表的常用方法 有如下两种: 1、头插法建表 该方法从一个空表开始,重复读入数据,生 成新结点,将读入数据存放到新结点的数据域 中,然后将新结点插入到当前链表的表头上, 直到读入结束标志为止。
定义头指针head typedef listnode *linklist; linklist head; 或者 listnode *head;
12
动态开辟和释放结点空间
开辟空间通过标准函数malloc()实现, 例如:
listnode *p; p=(listnode*)malloc(sizeof(listnode));
2
2.2 线性表的顺序存储结构及实现
例:(34, 23, 67, 43) :( ) 34 23 67 43 4
用什么属性来描述顺序表? 用什么属性来描述顺序表? 存储空间的起始位置 顺序表的容量(最大长度) 顺序表的容量(最大长度) 顺序表的当前长度
3
2.2 线性表的顺序存储结构及实现
例:(34, 23, 67, 43) :( ) 34 23 67 43 4
7
这两部分组成了链表中的结点结构:
data
next
其中:data域是数据域,用来存放结点的值。next 是指针域(亦称链域),用来存放结点的直接后继 的地址(或位置)。链表正是通过每个结点的链域 将线性表的n个结点按其逻辑次序链接在一起的。由 于上述链表的每一个结只有一个链域,故将这种链 表称为单链表(Single Linked)。
22
Biblioteka Baidu
2.3 线性表的链接存储结构及实现
单链表
0200
空表和非空表不统一,缺点? 空表和非空表不统一,缺点? 如何将空表与非空表统一? 如何将空表与非空表统一?
0208
空表 first=NULL 非空表 first a 1 a2 an ∧
0300
0325
… a2 0325 a1 0200 … a4 ∧ … a3 0300 …
6
2.3.1 线性链表
链表是指用一组任意的存储单元来依次存放 链表 线性表的结点,这组存储单元即可以是连续 的,也可以是不连续的,甚至是零散分布在 内存中的任意位置上的。 链表中结点的逻辑次序和物理次序不一定相 同。 为了能正确表示结点间的逻辑关系,在存储 每个结点值的同时,还必须存储指示其后继 结点的地址(或位置)信息,这个信息称为 指针(pointer)或链(link)。
32
else return NULL; } 2、按值查找 按值查找是在链表中,查找是否有结点 值等于给定值key的结点,若有的话,则返回 首次找到的其值为key的结点的存储位置;否 则返回NULL。查找过程从开始结点出发,顺着 链表逐个将结点的值和给定值key作比较。其 算法如下:
33
void locatenode(linklist head,int key) { listnode * p=head–>next; while( p && p–>data!=key) p=p–>next; return p; }
17
算法: Void creater(linklist &head) { char ch; listnode *p,*r; head=NULL;r=NULL; while((ch=getchar( )!=‵\n′){ p=(listnode *)malloc(sizeof(listnode)); p–>data=ch;
第二章 线性表
本章的基本内容是: 本章的基本内容是:
线性表的逻辑结构 线性表的顺序存储及实现 线性表的链接存储及实现 顺序表和单链表的比较 线性表的其他存储及实现
1
回 顾 2.2 线性表的顺序存储结构及实现 例:(34, 23, 67, 43) :( ) 34 23 67 43 4
存储要点
用一段地址连续的存储单元 用一段地址连续的存储单元 连续 依次存储线性表中的数据元素 依次存储线性表中的数据元素
8
显然,单链表中每个结点的存储地址是存放在其前趋 结点next域中,而开始结点无前趋,故应设头指针 head指向开始结点。同时,由于终端结点无后继,故 终端结点的指针域为空,即null(图示中也可用^表 示)。 例1、线性表:(bat,cat,eat,fat,hat,jat,lat,mat)
9
单链表示意图如下:
该算法的执行时间亦与输入实例中的的取值key有关, 其平均时间复杂度的分析类似于按序号查找, 也为O(n)。 34
三、插入运算
相关文档
最新文档