第3讲 线性表的链式存储结构-1

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

(2) 查找运算
按值查找: 按值查找: 在链表中, 查找第一个值为x的结点 若有, 的结点, 在链表中 , 查找第一个值为 的结点 , 若有 , 则 返回首次找到的值为x的结点的存储位置 的结点的存储位置; 返回首次找到的值为 的结点的存储位置;否则返回 Null. 算法思想: 算法思想: 从开始结点出发,顺链逐个结点的值和给定值x作 从开始结点出发,顺链逐个结点的值和给定值 作 比较。 比较。 算法描述( 算法描述(略)
带头结点的单链表
H
^ 空表
H
头结点
开始结点
a1 … an
^
非空表
无论链表是否为空, 无论链表是否为空,其头指针是指向头结点的 非空指针, 非空指针,所以表的第一个结点和其它结点的 操作一致。 操作一致。
/*带头结点的尾插法建立单链表,返回表头指针* /*带头结点的尾插法建立单链表,返回表头指针*/ 带头结点的尾插法建立单链表 LNode * CreateList() {Char ch; LNode *head,*p,*r; ;/*生成头结点 ));/*生成头结点* head=malloc(sizeof(LNode ));/*生成头结点*/ /*尾指针初值指向头结点 尾指针初值指向头结点* r=head; /*尾指针初值指向头结点*/ ch=getchar(); /*“ 为输入结束符* /*“$“为输入结束符*/ while(ch!=‘$’) p=( *) 生成新结点* {p=(LNode *)malloc(sizeof(LNode )); /生成新结点*/ p->data=ch; /*新结点插入表尾 新结点插入表尾* r->next=p; /*新结点插入表尾*/ /*尾指针 指向新的表尾* 尾指针r r=p; /*尾指针r指向新的表尾*/ /*读下一结点 读下一结点* ch=getchar(); /*读下一结点*/ } r->next=Null; return head; 13 } /* CreateList */
head a1 a2

an ^
线性链表逻辑状态
结点的组成
数据域
指针域
数据域: 表示数据元素自身值。 数据域 表示数据元素自身值。 指针域(链域) 表示与其它结点关系。 指针域(链域): 表示与其它结点关系。
单链表:每个结点只有一个链域。 单链表:每个结点只有一个链域。 开始结点:(无前趋)用头指针指向之。 开始结点 (无前趋)用头指针指向之。 最后一个结点(尾结点 指针为空(无后继), 尾结点):指针为空 最后一个结点 尾结点 指针为空(无后继), 表示。 用^或Null表示。 或 表示 表中其它结点:由其前趋的指针域指向之 由其前趋的指针域指向之。 表中其它结点 由其前趋的指针域指向之。 h a1 a2
指针p与指向的结点关系示意图 指针 与指向的结点关系示意图 data next p 结点 (*p)
P: 指向链表中某一结点的指针 *p: 表示由指针 所指向的结点 表示由指针p所指向的结点
单链表的基本运算 (1)建立单链表 )
①头插法建表: 头插法建表: 思想:从一个空表开始,重复读入数据,生成新结点, 思想:从一个空表开始,重复读入数据,生成新结点, 将读入数据存放在新结点的数据域中, 将读入数据存放在新结点的数据域中,然后将新结点插 入到当前链表的表头上,直到读入结束标志为止。 入到当前链表的表头上,直到读入结束标志为止。 H
H H
k0 ^
k1

kn-1 ^
带头结点的单链表
单链表的描 述
typedef struct LNode { ElemType data; struct LNode *next; }LNode, *LinkList
/*结点类型定义 结点类型定义*/ 结点类型定义 /*数据域 数据域*/ 数据域 /*next为指针域 为指针域*/ 为指针域
④ C ③ B A ^
P

D②
注:头插法生成的链表中结 点的次序和输入的顺序相反。 点的次序和输入的顺序相反。
LNode *CreateList() { Char ch; LNode *head,*p; head=Null; /*链表开始为空*/ ch=getchar(); /*读入第一个结点的值*/ while(ch!=‘$’) {p=(LNode*)malloc(sizeof(LNode));/生成新结点*/ p->data=ch; p->next=head; 逐个插入字符, 逐个插入字符,以 head=p; 为结束符, “$“为结束符,返 为结束符 ch=getchar(); 回单链表头指针 } return head; }
(3) 插入运算
在结点a和 之间插入一个数据元素 在结点 和b之间插入一个数据元素 x p p a b s x a
typedef struct LNode { ElemType data; struct LNode *next; }LNode, *LinkList LinkList P,S;
b
s=(LNode*)malloc(sizeof(LNode )); s->data=x; s->next=p->next; p->next=s;
附:在带头结点的单链表head中,将值为x的新结点插入 *P之前。 INSERTBEFORE(head,p,x) LNode *head,*p; datatype x; {LNode *q; s=(LNode*)malloc(sizeof(LNode )); s->data=x; q=head;
/*从头指针开始*/
7
②尾插建表法 算法思想: 算法思想: 将新结点插入到当前Leabharlann Baidu表的表尾上, 将新结点插入到当前链表的表尾上,可增加一 个尾指针r,使其始终指向链表的尾结点。 个尾指针 ,使其始终指向链表的尾结点。
H A B C
r
③ 尾插建表可使生 成的结点次序和 输入的顺序相同 ①
p

D ^

LNode *CreateList() {Char ch; /*逐个插入字符,以“$“为结束符,返回单链表头指针 逐个插入字符, 为结束符, 逐个插入字符 为结束符 返回单链表头指针*/ LNode *head,*p,*r; head=NULL; /*链表开始为空 链表开始为空*/ 链表开始为空 r=NULL; /*尾指针初值为空 尾指针初值为空*/ 尾指针初值为空 ch=getchar(); /*读入第一个结点的值 读入第一个结点的值*/ 读入第一个结点的值 while(ch!=‘$’) /*“$“为输入结束符 为输入结束符*/ 为输入结束符
9
头、尾插法建表分析: 尾插法建表分析: 尾插法建表由于没有生成(附加) 头、尾插法建表由于没有生成(附加) 头结点, 头结点,因此开始结点和其它结点的插入 处理并不一样,原因是开始结点的位置存 处理并不一样, 放在头指针中, 放在头指针中,而其余结点的位置是在其 前趋结点的指针域 。
10
③尾插法建表的改进算法 思想: 思想: 在第一个结点之前附设头结点 头结点, 在第一个结点之前附设头结点,使第一 个结点和其余结点的插入操作一致。 个结点和其余结点的插入操作一致。 头结点的数据域: 头结点的数据域:可有可无 头结点的指针域:指向第一个结点的指针。 头结点的指针域:指向第一个结点的指针。
{ p=(LNode*)malloc(sizeof(LNode )); /生成新结点 生成新结点*/ 生成新结点
p->data=ch; if (head==NULL) head=p; else r->next=p; r=p
ch=getchar();
}
If(r!=NULL) r->next=NULL; return head; } /* CreateList */

an ^
空表: 头指针为空。 空表 头指针为空。 头结点: 头结点 其指针域 指向表中第一个结点的指 针。 单链表:每个结点只有一个链域。 单链表:每个结点只有一个链域。 单链表的描述:单链表由头指针唯一确定, 单链表的描述:单链表由头指针唯一确定, 因此单链表可以用头指针的名字来命名。 因此单链表可以用头指针的名字来命名。 例如:若头指针为head,则可把链表称为 例如:若头指针为 则可把链表称为 “表head”。 。
While(q->next!=p) q=q->next; /*找*p的前趋结点*/ s->next=p;q->next=s; /*将*s插入*p之前*/ }
16
2.3 链接表示
1、单链表(线性链表) 、单链表(线性链表) 用一组任意的存储单元存放线性表的数据元素。 用一组任意的存储单元存放线性表的数据元素。 任意的存储单元存放线性表的数据元素 链表的特点: 链表的特点: 链表中结点的逻辑次序和物理次序不一定相同。即: 链表中结点的逻辑次序和物理次序不一定相同。 逻辑上相邻未必在物理上相邻。 逻辑上相邻未必在物理上相邻。结点之间的相对位置由 链表中的指针域指示, 链表中的指针域指示,而结点在存储器中的存储位置是 随意的。 随意的。
相关文档
最新文档