第7章树和二叉树-4(构造和线索)_第1页
第7章树和二叉树-4(构造和线索)_第2页
第7章树和二叉树-4(构造和线索)_第3页
第7章树和二叉树-4(构造和线索)_第4页
第7章树和二叉树-4(构造和线索)_第5页
已阅读5页,还剩28页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

7.2二叉树的概念和性质7.3二叉树的存储结构7.4二叉树基本运算及其实现7.8哈夫曼树7.7线索二叉树7.6二叉树的构造7.5二叉树的遍历7.9并查集第7章树和二叉树

7.1树的概念1/33假设二叉树中每个结点值唯一(均为单个字符)给定若干个遍历序列二叉树构造7.6二叉树的构造7.6二叉树的构造2/33同一棵二叉树具有唯一先序序列、中序序列和后序序列。但不同的二叉树可能具有相同的先序序列、中序序列或后序序列。回顾ABCABC先序序列均为ABC例如7.6二叉树的构造3/33给定一棵二叉树的一种遍历序列(先序序列、中序序列或后序序列)不能唯一确定该二叉树。结论7.6二叉树的构造4/33

给定一棵二叉树的先序序列和中序序列能唯一确定这棵二叉树。

给定一棵二叉树的中序序列和后序序列能唯一确定这棵二叉树。

给定一棵二叉树的先序序列和后序序列能唯一确定这棵二叉树。

以下命题成立否?那么给定两种遍历序列呢?7.6二叉树的构造5/33先序序列中序序列后序序列层次序列根结点根结点根结点已知时,可以确定左右子树各种遍历序列提供的信息:根结点7.6二叉树的构造6/33

定理7.1:任何n(n≥0)个不同结点的二叉树,都可由它的中序序列和先序序列唯一地确定。先序序列:a0

a1

ak

ak+1

an-1左子树先序序列,有k个结点右子树先序序列,有n-k-1个结点中序序列:b0

b1

…bk-1

bk

bk+1

…bn-1左子树中序序列,有k个结点右子树中序序列,有n-k-1个结点通过根结点a0在中序序列中找到bka0先序:a1

ak中序:b0

bk-1左子树先序:ak+1

an-1中序:bk+1

bn-1右子树7.6二叉树的构造7/33例如,已知先序序列为ABDGCEF,中序序列为DGBAECF,构造该二叉树。

二叉树构造完毕先序:ABDGCEF中序:DGBAECFA先序:BDG中序:DGB

B先序:CEF中序:ECFC先序:E中序:E

E先序:F中序:F

F先序:DG中序:DGD先序:G中序:G

G7.6二叉树的构造8/33BTNode*CreateBT1(char*pre,char*in,intn){BTNode*s;char*p;intk;

if(n<=0)returnNULL;

s=(BTNode*)malloc(sizeof(BTNode)); //创建根结点

s->data=*pre;

for(p=in;p<in+n;p++) //在in中找为pre的位置kif(*p==*pre)

break;

k=p-in;由上述定理得到以下构造二叉树的算法:7.6二叉树的构造9/33s->lchild=CreateBT1(pre+1,in,k);//构造左子树

s->rchild=CreateBT1(pre+k+1,p+1,n-k-1);//构造右子树

returns;}先序遍历的思路先序pre:a0

a1

ak-1ak

ak+1…

an-2an-1中序in:b0

b1

bk-1bk

bk+1…

bn-2

bn-1ppre+1pre+k+1p+1in7.6二叉树的构造10/33

定理7.2:任何n(n≥0)个不同结点的二叉树,都可由它的中序序列和后序序列唯一地确定。后序序列:a0

a1

ak-1

ak

an-2an-1左子树后序序列,有k个结点右子树后序序列,有n-k-1个结点中序序列:b0

b1

bk-1

bk

bk+1

bn-1左子树中序序列,有k个结点右子树中序序列,有n-k-1个结点通过根结点an-1在中序序列中找到bkan-1后序:a0

ak-1中序:b0

bk-1左子树后序:ak

an-2中序:bk+1

bn-1右子树7.6二叉树的构造11/33例如,已知中序序列为DGBAECF,后序序列为GDBEFCA。对应的构造该二叉树。二叉树构造完毕后序:GDBEFCA中序:DGBAECFABCEFDG后序:GDB中序:DGB后序:EFC中序:ECF后序:GD中序:DG后序:G中序:G后序:E中序:E后序:F中序:F7.6二叉树的构造12/33BTNode*CreateBT2(char*post,char*in,intn){BTNode*b;charr,*p;intk;if(n<=0)returnNULL;r=*(post+n-1); //根结点值b=(BTNode*)malloc(sizeof(BTNode)); //创建二叉树结点bb->data=r;

for(p=in;p<in+n;p++)

//在in中查找根结点if(*p==r)break;k=p-in;

//k为根结点在in中的下标

由上述定理得到以下构造二叉树的算法:7.6二叉树的构造13/33b->lchild=CreateBT2(post,in,k); //递归构造左子树b->rchild=CreateBT2(post+k,p+1,n-k-1);//递归构造右子树returnb;}先序遍历的思路后序post:a0

a1

ak-1

ak

ak+1…

an-2an-1中序in:b0

b1

bk-1

bk

bk+1

bn-2

bn-1ppostpost+kp+1in7.6二叉树的构造14/33【例7.19】设计一个算法将二叉树的顺序存储结构转换成二叉链存储结构。设二叉树的顺序存储结构为a。由f(a,i)返回创建的以a[i]为根结点的二叉链存储结构。由f(a,1)返回创建的二叉链存储结构的根结点指针b。f(a,i)=NULL

当i大于MaxSizef(a,i)=NULL

当i对应的结点为空f(a,i)=b(创建根结点b,其data值为a[i]); 其他情况

b->lchild=f(a,2*i);

b->rchild=f(a,2*i+1))b

12a递归模型:解7.6二叉树的构造15/33BTNode*trans(SqBTreea,inti){BTNode*b;

if(i>MaxSize)returnNULL;

if(a[i]==‘#’)returnNULL;

//空结点时返回NULLb=(BTNode*)malloc(sizeof(BTNode)); //创建根结点

b->data=a[i];

b->lchild=trans(a,2*i);

//递归创建左子树

b->rchild=trans(a,2*i+1);

//递归创建右子树

return(b);

//返回根结点}对应的递归算法如下:先序遍历的思路7.6二叉树的构造16/33#include"btree.cpp"typedefcharElemtype;typedefElemTypeSqBTree[MaxSize];BTNode*trans(SqBTreea,inti){…

}intmain(){BTNode*b;SqBTreea="0ABCD#EF##G####################";b=trans(a,1);printf("b:");DispBTree(b);printf("\n");DestroyBTree(b);}7.6二叉树的构造17/33对于具有n个结点的二叉树,采用二叉链存储结构时,每个结点有两个指针域,总共有2n个指针域。其中只有n-1个结点被有效指针所指向,即有n-1个非空指针域。所以共有2n-(n-1)=n+1个空链域。

7.7.1线索二叉树的概念回顾:7.7线索二叉树7.7线索二叉树18/33采用某种方法遍历二叉树的结果是一个结点的线性序列。修改空链域改为存放指向结点的前驱和后继结点的地址。这样的指向该线性序列中的“前驱”和“后继”的指针,称作线索(thread)。创建线索的过程称为线索化。线索化的二叉树称为线索二叉树。显然线索二叉树与采用的遍历方法相关,有先序线索二叉树、中序线索二叉树和后序线索二叉树。线索二叉树的目的是提高该遍历过程的效率。相关概念:7.7.1线索二叉树的概念19/33

在结点的存储结构上增加两个标志位来区分这两种情况:

ltag

lchilddatarchild

rtag左标志ltag0表示lchild指向左孩子结点1表示lchild指向前驱结点,即线索这样,每个结点的存储结构如下:右标志rtag0表示rchild指向右孩子结点1表示rchild指向后继结点,即线索为了方便算法设计,在线索二叉树中再增加一个头结点。7.7.1线索二叉树的概念20/33typedefstructnode

{ElemTypedata; //结点数据域

intltag,rtag; //增加的线索标记

structnode*lchild; //左孩子或线索指针

structnode*rchild; //右孩子或线索指针

}

TBTNode;

//线索树结点类型定义线索化二叉树中结点的类型定义如下:7.7.1线索二叉树的概念21/330A

01E10C01F10B11

D

01G10///1中序线索二叉树(在线索二叉树中再增加一个头结点)7.7.1线索二叉树的概念22/33建立某种次序的线索二叉树过程:7.7.2线索化二叉树以中序线索二叉树为例,讨论建立线索二叉树的算法。

以该遍历方法遍历一棵二叉树。在遍历的过程中,检查当前访问结点的左、右指针域是否为空:如果左指针域为空,将它改为指向前驱结点的线索;如果右指针域为空,将它改为指向后继结点的线索。7.7.2线索化二叉树23/33CreatThread(b)算法:对以二叉链存储的二叉树b进行中序线索化,并返回线索化后头结点的指针root。Thread(p)算法:对以p为根结点的二叉树子树的中序线索化。

建立中序线索二叉树的算法7.7.2线索化二叉树24/33p总是指向当前线索化的结点。pre作为全局变量,指向刚刚访问过的结点。pre结点是p结点的中序前驱结点,p结点是pre结点的中序后继结点。在中序遍历中:中序序列的前驱结点pre中序序列的后继结点p若rchild为NULL,改为后继线索若lchild为NULL,改为前驱线索7.7.2线索化二叉树25/330A01E10C01

F

10///10

B

11D11G1中序序列:中序线索化演示中序线索树建立完毕prepDGBAECFp=NULL26/33TBTNode*pre; //全局变量TBTNode*CreatThread(TBTNode*b)

//中序线索化二叉树{TBTNode*root;

root=(TBTNode*)malloc(sizeof(TBTNode));//创建头结点

if(b==NULL)

//空二叉树

{root->rchild=root->rchild=root;root->ltag=root->rtag=1;

}1///1头结点root7.7.2线索化二叉树27/33else{root->lchild=b;

root->ltag=0;root->rtag=1;

pre=root;

//pre是p的前驱结点,供加线索用

Thread(b);

//中序遍历线索化二叉树

pre->rchild=root;

//最后加入指向头结点的线索

pre->rtag=1;

root->rchild=pre;

//头结点右线索化

}

returnroot;}0///10A

0根结点头结点1

F1尾结点pre7.7.2线索化二叉树28/33voidThread(TBTNode*&p)

//对二叉树b进行中序线索化{if(p!=NULL)

{

Thread(p->lchild);

//左子树线索化if(p->lchild==NULL)

//前驱线索化{p->lchild=pre;p->ltag=1;}

//建立当前结点的前驱线索

elsep->ltag=0;if(pre->rchild==NULL) //后继线索化

{pre->rchild=p;pre->rtag=1;} //建立前驱结点的后继线索

elsepre->rtag=0;

pre=p;

Thread(p->rchild);

//递归调用右子树线索化

}}中序遍历(递归)算法7.7.2线索化二叉树29/33找到开始结点,从开始结点出发。反复找到该结点在该次序下的后继结点,直到头结点。

7

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论