习题课(树与二叉树)_第1页
习题课(树与二叉树)_第2页
习题课(树与二叉树)_第3页
习题课(树与二叉树)_第4页
习题课(树与二叉树)_第5页
已阅读5页,还剩17页未读 继续免费阅读

下载本文档

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

文档简介

1、精选优质文档-倾情为你奉上精选优质文档-倾情为你奉上专心-专注-专业专心-专注-专业精选优质文档-倾情为你奉上专心-专注-专业第六章 树和二叉树6.33 int ex633(int u,int v)/判断u是否v的子孙,是返回1,否则返回0if(u=v) return 1; else if(Lv) if (ex633(u,Lv) return 1; if(Rv) if (ex633(u,Rv) return 1; return 0; 6.34 假定用两个一维数组LN和RN作为有N个结点1,2,, N的二叉树的存储结构。Li和Ri分别指示结点 i的左儿子和右儿子;Li=0(Ri=0)表示i的左(

2、右)儿子为空。试写一个算法,由L和R建立一个一维数组TN,使Ti存放结点i的父亲;然后再写一个判别结点U是否为结点V的后代的算法。【哈尔滨工业大学 1999 七 (14分)】【华南师范大学2000 六(17分)】解:题目分析由指示结点i 左儿子和右儿子的两个一维数组Li和Ri,很容易建立指示结点i 的双亲的一维数组Ti,根据T数组,判断结点U是否是结点V后代的算法,转为判断结点V是否是结点U的祖先的问题。int Generate(int U,int V,int N,int L,int R,int T)/*L和R是含有N个元素且指示二叉树结点i左儿子和右儿子的一维数组,本算法据此建立结点i的双亲

3、数组T,并判断结点U是否是结点V的后代。*/for(i=1;i=N;i+) Ti=0; /T数组初始化 for (i=1;i=N;i+) /根据L和R填写T if(Li!=0) TLi=i; /若i的左子女是L,则L的双亲是i for(i=1;ilchild,T2-lchild);b2=ex636(T1-rchild,T2-rchild); return b1&b2; 6.37 void ex637(BiTree T)/先序遍历二叉树的非递归算法InitStack(S); Push(S,T); while(!StackEmpty(S) while(GetTop(S,p)&p) coutdata

4、; push(S,p-lchild); pop(S,p); if(!StackEmpty(S) pop(S,p); push(S,p-rchild); 6.37利用栈的基本操作写出先序遍历二叉树的非递归算法,要求进栈的元素最少。 【山东科技大学 2002 四、 (10分)】解:题目分析 先序遍历二叉树的非递归算法,要求进栈元素少,意味着空指针不进栈。void PreOrder(Bitree bt) /对二叉树bt进行非递归先序遍历int top=0; Bitree s; /top是栈s的栈顶指针,栈中元素是树结点指针,栈容量足够大 while(bt!=null | top0) while(bt

5、!=null) coutdata; /访问根结点if(bt-rchlid) s+top=bt-rchild; /若有右子女,则右子女进栈bt=bt-lchild; if (top0) bt=stop-; 6.38 void ex638(BiTree T)/后序遍历二叉树的非递归算法,用栈 BiTree s100; char tag100; p=T;top=0; do while(p)tagtop=L;stop=p;top+;p=p-lchild; while(top0&tagtop-1=R)top-;p=stop;coutdata0)tagtop-1=R;p=stop-1-rchild;whi

6、le(top0);6.43设一棵二叉树以二叉链表为存贮结构,结点结构为(lchild, data,rchild),设计一个算法将二叉树中所有结点的左,右子树相互交换。【福州大学 1998 四、2 (10分)】解: void exchange(BiTree &bt)/将二叉树bt所有结点的左右子树交换 if(bt) BiTree s; s=bt-lchild; bt-lchild=bt-rchild; bt-rchild=s; /左右子女交换 exchange(bt-lchild);/交换左子树上所有结点左右子树 exchange(bt-rchild);/交换右子树上所有结点左右子树 算法讨论将

7、上述算法中两个递归调用语句放在前面,将交换语句放在最后,则是以后序遍历方式交换所有结点的左右子树。中序遍历不适合本题。下面是本题的非递归算法void exchange(BiTree &bt) /交换二叉树中各结点的左右孩子的非递归算法int top=0; BiTree s,t,p; /s是二叉树的结点指针的栈,容量足够大 if(bt) s+top=bt;while(top0) t=stop-;if(t-lchild|t-rchild)p=t-lchild;t-lchild=t-rchild; t-rchild=p;/交换左右子树 if(t-lchild) s+top=t-lchild; /左子

8、女入栈 if(t-rchild) s+top=t-rchild; /右子女入栈 /while(top0)/if(bt) / 结束exchange6.47 void ex647(BiTree T)/层序遍历二叉树InitQueue(Q);EnQueue(Q,T);while(!QueueEmpty(Q)DeQueue(Q,p);coutdata;if(p-lchild) EnQueue(Q,p-lchild);if(p-rchild) EnQueue(Q,p-rchild); 6.56 BiThrTree ex656(BiThrTree p)/在先序后继线索二叉树中查找结点p的先序后继if(p-

9、ltag=Link) return p-lchild; else return p-rchild;6.57 BiThrTree ex657(BiThrTree p)/在后序后继线索二叉树中查找结点p的后序后继,并返回指针if(!p-parent) return NULL; else if(p=p-parent-lchild&p-parent-rchild) q=p-parent-rchild; while(q-lchild|q-rchild) if(q-lchild) q=q-lchild; else q=q-rchild; return q; else return p-parent;例1二

10、叉树采用二叉链表存储:(1)编写计算整个二叉树高度的算法(二叉树的高度也叫二叉树的深度)。(2)编写计算二叉树最大宽度的算法(二叉树的最大宽度是二叉树所有层中结点个数的最大值)。【西北大学 2001 四】解:题目分析 求二叉树高度的算法略。求最大宽度可采用层次遍历的方法,记下各层结点数,每层遍历完毕,若结点数大于原先最大宽度,则修改最大宽度。int Width(BiTree bt)/求二叉树bt的最大宽度if (bt=null) return (0); /空二叉树宽度为0 else BiTree Q;/Q是队列,元素为二叉树结点指针,容量足够大front=1;rear=1;last=1;/fr

11、ont头指针,rear尾指针,last同层最右结点在队列中的位置temp=0; maxw=0; /temp记局部宽度, maxw记最大宽度 Qrear=bt; /根结点入队列 while(frontlchild!=null) Q+rear=p-lchild; /左子女入队 if(p-rchild!=null) Q+rear=p-rchild; /右子女入队 if (frontlast) /一层结束 last=rear; if(tempmaxw) maxw=temp; /last指向下层最右元素, 更新当前最大宽度 temp=0;/if /while return (maxw);/结束width

12、例2要求二叉树按二叉链表形式存储,(1)写一个建立二叉树的算法。(2)写一个判别给定的二叉树是否是完全二叉树的算法。完全二叉树定义为:深度为K,具有N个结点的二叉树的每个结点都与深度为K的满二叉树中编号从1至N的结点一一对应。此题以此定义为准。【西北大学 2000 六 (12分)】【青岛海洋大学 1999 六(15分)】【南京航空航天大学2001十(10分)】【北方交通大学 1997 八 (20分)】【哈尔滨工业大学 2000 十一 (14分)】【南开大学 1997 四 (16分)】【北京邮电大学 1994 九 (20分)】解:题目分析二叉树是递归定义的,以递归方式建立最简单。判定是否是完全二

13、叉树,可以使用队列,在遍历中利用完全二叉树“若某结点无左子女就不应有右子女”的原则进行判断。BiTree Creat() /建立二叉树的二叉链表形式的存储结构int x;BiTree bt; scanf(“%d”,&x); /本题假定结点数据域为整型 if(x=0) bt=null; else if(x0) bt=(BiNode *)malloc(sizeof(BiNode);bt-data=x; bt-lchild=creat();bt-rchild=creat(); else error(“输入错误”); return(bt);/结束 BiTreeint JudgeComplete(BiT

14、ree bt) /判断二叉树是否是完全二叉树,如是,返回1,否则,返回0int tag=0; BiTree p=bt, Q; / Q是队列,元素是二叉树结点指针,容量足够大 if(p=null) return (1); InitQueue(Q); EnQueue(Q,p); /初始化队列,根结点指针入队 while (!QueueEmpty(Q) p=DeQueue(Q); /出队 if (p-lchild & !tag) EnQueue(Q,p-lchild); /左子女入队 else if (p-lchild) return 0; /前边已有结点为空,本结点不空else tag=1; /首

15、次出现结点为空 if (p-rchild & !tag) EnQueue(Q,p-rchild); /右子女入队 else if (p-rchild) return 0; else tag=1; /while return 1; /JudgeComplete算法讨论完全二叉树证明还有其它方法。判断时易犯错误是证明其左子树和右子数都是完全二叉树,由此推出整棵二叉树必是完全二叉树的错误结论。例3已知一棵二叉树的中序序列和后序序列,写一个建立该二叉树的二叉链表存储结构的算法。【东北大学 1999 六、3 (12分)】解:BiTree IntoPost(ElemType in,ElemType pos

16、t,int l1,int h1,int l2,int h2)/*in和post是二叉树的中序序列和后序序列,l1,h1,l2,h2分别是两序列第一和最后结点的下标*/BiTree bt=(BiTree)malloc(sizeof(BiNode); bt-data=posth2;/后序遍历序列最后的元素是根结点 for(i=l1;ilchild=null; /处理左子树 elsebt-lchild=IntoPost(in,post,l1,i-1,l2,l2+i-l1-1); if(i=h1) bt-rchild=null; /处理右子树 elsebt-rchild=IntoPost(in,pos

17、t,i+1,h1,l2+i-l1,h2-1); return(bt);例4已知具有n个结点二叉树的中序遍历序列与后序遍历序列分别存放于数组IN1:n和POST1:n中,(设二叉树各结点的数据值均不相同)。请写一建立该二叉树的二叉链表结构的非递归算法。该二叉链表的链结点结构为(lchild,data,rchild),其中data为数据域,lchild与rhild分别为指向结点左、右孩子的指针(当孩子结点不存在时,相应指针域为空,用NULL表示)。【北京航空航天大学 1998 六 (15分)】解:题目分析已知二叉树中序序列与后序序列,上题以递归算法建立了二叉树,本题是非递归算法。void InPo

18、stCreat(BiTree &bt,ElemType IN,ElemType POST,int l1,int h1,int l2,int h2)/*由二叉树的中序序列IN和后序序列POST建立二叉树,l1,h1和l2,h2分别是中序序列和后序序列第一和最后元素的下标,初始调用时,l1=l2=1,h1=h2=n。*/typedef struct int l1,h1,l2,h2; BiTree t; node; node s,p;/s为栈,容量足够大 BiTree bt=(BiTree)malloc(sizeof(BiNode); int top=0,i; p.l1=l1; p.h1=h1; p

19、.l2=l2; p.h2=h2; p.t=bt; s+top=p;/初始化 while(top0) p=stop-; bt=p.t; l1=p.l1; h1=p.h1;l2=p.l2; h2=p.h2;/取出栈顶数据 for(i=l1;idata=POSTh2; /根结点的值 if(i=l1) bt-lchild=null; /bt无左子树 else /将建立左子树的数据入栈bt-lchild=(BiTree)malloc(sizeof(BiNode); p.t=bt-lchild;p.l1=l1; p.h1=i-1; p.l2=l2; p.h2=l2+i-l1-1; s+top=p; if(

20、i=h1) bt-rchild=null; /bt无右子树else/右子树数据入栈bt-rchild=(BiTree)malloc(sizeof(BiNode); p.t=bt-rchild;p.l1=i+1; p.h1=h1; p.l2=l2+i-l1; p.h2=h2-1; s+top=p; / while(top0)/结束InPostCreat例5编程求以孩子兄弟表示法存储的森林的叶子结点数。要求描述结构。【北京工业大学2000五(10分)】【北京轻工业学院2000四(15分)】解:题目分析当森林(树)以孩子兄弟表示法存储时,若结点没有孩子(firstchild=null),则它必是叶子

21、,总的叶子结点个数是孩子子树(firstchild)上的叶子数和兄弟(nextsibling)子树上叶结点个数之和。typedef struct CSNodeElemType data;/数据域struct CSNode *firstchild, *nextsibling;/孩子与兄弟域 CSNode,*CSTree;int Leaves (CSTree t)/计算以孩子-兄弟表示法存储的森林的叶子数if(t=NULL)return(0); else if(t-firstchild=NULL) /若结点无孩子,则该结点必是叶子 return(1+Leaves(t-nextsibling); /

22、返回叶子结点和其兄弟子树中的叶子结点数else /孩子子树和兄弟子树中叶子数之和return(Leaves(t-firstchild)+Leaves(t-nextsibling); /结束Leaves例6以孩子兄弟链表为存储结构,请设计递归和非递归算法求树的深度。【北方交通大学1999五(18分)】【南京航空航天大学 2000 九】解:题目分析由孩子兄弟链表表示的树,求高度的递归模型是:若树为空,高度为零;若第一子女为空,高度为1和兄弟子树的高度的大者;否则,高度为第一子女树高度加1和兄弟子树高度的大者。其非递归算法使用队列,逐层遍历树,取得树的高度。int Height(CSTree bt)

23、 /递归求以孩子兄弟链表表示的树的深度int hc,hs; if (bt=null) return (0);else if (!bt-firstchild) hs= Height(bt-nextsibling); if(hs1)return(hs); else return (1);/子女空,查兄弟的深度 else / 结点既有第一子女又有兄弟,高度取子女高度+1和兄弟子树高度的大者hc=Height(bt-firstchild);/第一子女树高hs=Height(bt-nextsibling);/兄弟树高if(hc+1hs)return(hc+1);else return (hs); /结束

24、Heightint Height(CSTree t) /非递归遍历求以孩子兄弟链表表示的树的深度if(t=null) return(0);elseint front=1,rear=1; /front,rear是队头队尾元素的指针int last=1,h=0; /last指向树中同层结点中最后一个结点,h是树的高度 Qrear=t; /Q是以树中结点为元素的队列while(frontfirstchild) /第一子女入队Q+rear=t-firstchild; t=t-nextsibling; /同层兄弟指针后移 if(frontlast)/本层结束,深度加1(初始深度为0) h+;last=r

25、ear; /last再移到指向当前层最右一个结点/while(front=last) /else/Height例7假设以双亲表示法作树的存储结构,写出双亲表示的类型说明,并编写求给定的树的深度的算法。(注:已知树中结点数)【清华大学 1994 七、 (15分)】解:题目分析 由于以双亲表示法作树的存储结构,找结点的双亲容易。因此我们可求出每一结点的层次,取其最大层次即树有深度。对每一结点,找其双亲,双亲的双亲,直至(根)结点双亲为0为止。int Depth(Ptree t) /求以双亲表示法为存储结构的树的深度,Ptree的定义参看教材int maxdepth=0;for(i=1;i0) te

26、mp+; f=t.nodesf.parent; / 深度加1,并取新的双亲if(tempmaxdepth) maxdepth=temp; /最大深度更新return(maxdepth);/返回树的深度 /结束Depth例25请设计一个算法,要求该算法把二叉树的叶子结点按从左到右的顺序连成一个单链表,表头指针为head。 二叉树按二叉链表方式存储,链接时用叶子结点的右指针域来存放单链表指针。分析你的算法的时、空复杂度。【华南师范大学 1999 六、2 (13分)】【清华大学 1997 三、 (10分)】解:题目分析叶子结点只有在遍历中才能知道,这里使用中序递归遍历。设置前驱结点指针pre,初始为

27、空。第一个叶子结点由指针head指向,遍历到叶子结点时,就将它前驱的rchild指针指向它,最后叶子结点的rchild为空。LinkList head,pre=null; /全局变量LinkList InOrder(BiTree bt)/*中序遍历二叉树bt,将叶子结点从左到右链成一个单链表,表头指针为head*/if(bt) InOrder(bt-lchild); /中序遍历左子树if(bt-lchild=null & bt-rchild=null) /叶子结点if(pre=null) head=bt; pre=bt; /处理第一个叶子结点 elsepre-rchild=bt; pre=bt

28、; /将叶子结点链入链表InOrder(bt-rchild); /中序遍历左子树pre-rchild=null; /设置链表尾 return(head); /InOrder时间复杂度为O(n),辅助变量使用head和pre,栈空间复杂度O(n)例26编写一算法,利用叶子结点中的空指针域将所有叶子结点链接为一带有头结点的双链表,算法返回头结点的地址。【东北大学 1999 四(13分)】解:题目分析 “双链”就利用二叉树结点的左右指针,重新定义左指针为指向前驱的指针,右指针是指向后继的指针,链表在遍历中建立,下面采用中序遍历二叉树。BiTree head=null,pre; /全局变量链表头指针h

29、ead,prevoid CreatLeafList(BiTree bt) /将BiTree 树中所有叶子结点链成带头结点的双链表if(bt) /若bt不空 CreatLeafList(bt-lchild); /中序遍历左子树 if(bt-lchild=null & bt-rchild=null) /叶子结点 if(head=null)/第一个叶子结点head=(BiTree)malloc(sizeof(BiNode); head-lchild=null; head-rchild=bt; /头结点的左链为空,右链指向第一个叶子结点 bt-lchild=head; pre=bt; /第一个叶子结点左链指向头结点,pre指向当前叶子结点 else /已不是第一个叶子结点 pre-rchild=bt; bt-lchild=pre; pre=bt; /当前叶子结点链入双链表 CreatLeafList(bt-rchild); /中序遍历右子树pre-rchild=null; /最后一个叶子结点的右链置空(链表结束标记) /if(bt) /结束CreatLeafList例33写出在中序线索二叉树里;找指定结点在后序下的前驱结点的算法。【河海大学1998

温馨提示

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

评论

0/150

提交评论