数据结构C语言版第六章 树和二叉树.docx

上传人:b****5 文档编号:27997922 上传时间:2023-07-07 格式:DOCX 页数:21 大小:56.98KB
下载 相关 举报
数据结构C语言版第六章 树和二叉树.docx_第1页
第1页 / 共21页
数据结构C语言版第六章 树和二叉树.docx_第2页
第2页 / 共21页
数据结构C语言版第六章 树和二叉树.docx_第3页
第3页 / 共21页
数据结构C语言版第六章 树和二叉树.docx_第4页
第4页 / 共21页
数据结构C语言版第六章 树和二叉树.docx_第5页
第5页 / 共21页
点击查看更多>>
下载资源
资源描述

数据结构C语言版第六章 树和二叉树.docx

《数据结构C语言版第六章 树和二叉树.docx》由会员分享,可在线阅读,更多相关《数据结构C语言版第六章 树和二叉树.docx(21页珍藏版)》请在冰豆网上搜索。

数据结构C语言版第六章 树和二叉树.docx

数据结构C语言版第六章树和二叉树

第六章树和二叉树

重点难点

要求掌握二叉树的性质和存储结构;熟练掌握二叉树的各种遍历算法,并能灵活运用遍历算法实现二叉树的其它操作;理解二叉树的线索化过程以及在中序线索化树上找给定结点的前驱和后继的方法;熟练掌握二叉树和树的各种存储结构及其建立的算法。

熟练掌握赫夫曼树和赫夫曼编码的构造方法;掌握树、森林与二叉树之间的相互转换方法。

典型例题

1.一棵度为2的有序树与一棵二叉树有何区别?

【解】  一棵度为二的有序树与一棵二叉树的区别在于:

有序树的结点次序是相对于另一结点而言的,如果有序树中的子树只有一个孩子时,这个孩子结点就无须区分其左右次序,而二叉树无论其孩子数是否为2,均需确定其左右次序,也就是说二叉树的结点次序不是相对于另一结点而言而是确定的。

2.已知一棵度为m的树中有n1个度为1的结点,n2个度为2的结点,...nm个度为m的结点,问该树中有多少片叶子?

【解】

   设该树中的叶子数为n0个。

该树中的总结点数为n个,则有:

        n=n0+n1+n2+…+nm

(1)

又有除根结点外,树中其他结点都有双亲结点,且是唯一的(由树中的分支表示),所以,有双亲的结点数为:

        n-1=0*n0+1*n1+2*n2+…+m*nm

(2)

 联立

(1)

(2)方程组可得:

 叶子数为:

n0=1+0*n1+1*n2+2*n3+...+(m-1)*nm

3.试找出分别满足下面条件的所有二叉树:

 

(1)前序序列和中序序列相同;

(2)中序序列和后序序列相同;

 (3)前序序列和后序序列相同;(4)前序、中序、后序序列均相同。

【解】

 

(1)前序序列和中序序列相同的二叉树是:

空二叉树或没有左子树的二叉树(右单支树)。

 

(2)中序序列和后序序列相同的二叉树是:

空二叉树或没有右子树的二叉树(左单支树)。

 (3)前序序列和后序序列相同的二叉树是:

空二叉树或只有根的二叉树。

 (4)前序、中序、后序序列均相同的二叉树:

空树或只有根结点的二叉树。

4.若二叉树中各结点的值均不相同,则由二叉树的前序序列和中序序列,或由其后序序列和中序序列均能唯一地确定一棵二叉树,但由前序序列和后序序列却不一定能唯一地确定一棵二叉树。

(1)已知一棵二叉树的前序序列和中序序列分别为ABDGHCEFI和GDHBAECIF,请画出此二叉树。

(2)已知一棵二叉树的在序序列和后序序列分别为BDCEAFHG和DECBHGFA,请画出此二叉树。

【解】

1)已知二叉树的前序序列为ABDGHCEFI和中序序列GDHBAECIF,则可以根据前序序列找到根结点为A,由此,通过中序序列可知它的两棵子树包分别含有GDHB和ECIF结点,又由前序序列可知B和C分别为两棵子树的根结点...以此类推可画出所有结点:

                      

○A

                     / \

                   ○B○C

                  /     /\

                ○D  ○E○F

               /\        /

            ○G○H  ○I

 

(2)以同样的方法可画出该二叉树:

○A

                    /\

                   ○B○F

                    \      \

                    ○C  ○G

                   /\      \

               ○D○E    ○H

 (3)这两棵不同的二叉树为:

                   ○A      ○A

                   /           \

                 ○B          ○B

5.假设用于通信的电文由字符集{a,b,c,d,e,f,g,h}中的字母构成,这8个字母在电文中出现的概率分别为{0.07,0.19,0.02,0.06,0.32,0.03,0.21,0.10}.

(1)为这8个字母设计哈夫曼编码。

(2)若用这三位二进制数(0…7)对这8个字母进行等长编码,则哈夫曼编码的平均码长是等长编码的百分之几?

它使电文总长平均压缩多少?

【解】

 

(1)哈夫曼编码

 

   根据上图可得编码表:

   a:

1001

   b:

01

   c:

10111

   d:

1010

   e:

11

   f:

10110

   g:

00

   h:

1000

  

(2)用三位二进行数进行的等长编码平均长度为3,而根据哈夫曼树编码的平均码长为:

      4*0.07+2*0.19+5*0.02+4*0.06+2*0.32+5*0.03+2*0.21+4*0.10=2.61

      2.61/3=0.87=87%

     其平均码长是等长码的87%。

所以平均压缩率为13%。

6.以二叉链表为存储结构,分别写出求二叉树结点总数及叶子总数的算法。

【解】

 思路:

(1)求结点数的递归定义为:

  若为空树,结点数为0

  若只有根结点,则结点数为1;

  否则,结点数为根结点的左子树结点数+右子树结点数+1

 

(2)求叶子数的递归定义为:

  若为空树,叶子数为0

  若只有根结点,则叶子数为1;

  否则,叶子数为根结点的左子树叶子数+右子树叶子数

 typedefcharDataType;//定义DataType类型

 typedefstructnode{

    DataTypedata;

    structnode*lchild,*rchild;//左右孩子子树

  }BinTNode;//结点类型

 typedefBinTNode*BinTree;//二叉树类型

 intNode(BinTreeT)

  {//算结点数

   if(T)

    if(T->lchild==NULL)&&(T->rchild==NULL)

     return1;

    elsereturnNode(T->lchild)+Node(T->rchild)+1;

   elsereturn0;

  }

 intLeaf(BinTreeT)

  {//算叶子数

   if(T)

    if(T->lchild==NULL)&&(T->rchild==NULL)

     return1;

    elsereturnLeaf(T->lchild)+Node(T->rchild);

   elsereturn0;

}

7.以二叉链表为存储结构,写一个拷贝二叉树的算法voidCopyTree(BinTreeroot,BinTree*newroot),其中新树的结点是动态申请的,为什么newroot要说明为BinTree型指针的指针?

解:

  因为调用函数只能进行值传递,当返回类型为void时,就必须把实参的地址传给函数,否则函数不会对实际参数进行任何操作,也就得不到所需结果了。

所以,newroot要说明为BinTree型指针

 voidCopyTree(BinTreeroot,BinTree*newroot)

  {//拷贝二叉树

   if(root)//如果结点非空

    {//按前序序列拷贝

     *newroot=(BinTNode*)malloc(sizeof(BinTNode));//生成新结点

     (*newroot)->data=root->data;//拷贝结点数据

     CopyTree(root->lchild,&(*newroot)->lchild);//拷贝左子树

     CopyTree(root->rchild,&(*newroot)->rchild);//拷贝右子树

    }

   else//如果结点为空

   *newroot=NULL;//将结点置空

  }

8.以二叉链表为存储结构,分别写出在二叉树中查找值为x的结点及求x所在结点在树中层数的算法。

解:

  根据上几题的算法可以得出本题的算法如下:

 #defineM10//假设二叉树最多的层数

 BinTreeSearchBTree(BinTree*T,DataTypex)

  {//以前序遍历算法查找值为x的结点

   if(*T)

    {

     if((*T)->data==x)return*T;

     SearchBTree(&(*T)->lchild,x);

     SearchBTree(&(*T)->rchild,x);

    }

  }

 intInLevel(BinTreeT,DataTypex)

  {

   intstaticl=0;//设一静态变量保存层数

   if(T)

    {

     if(l==0)//若是访问根结点

      {

       l++;//第1层

       if(T->data==x)returnl;

       if(T->lchild||T->rchild)

        l++;//若根有子树,则层数加1

      }

     else

      {//访问子树结点

       if(T->data==x)returnl;

       if(T->lchild||T->rchild)

        l++;//若该结点有子树,则层数加1

       elsereturn0;

      }

     InLevel(T->lchild,x);//遍历左子树

     InLevel(T->rchild,x);//遍历右子树

    }

  }

9.一棵n个结点的完全二叉树以向量作为存储结构,试写一非递归算法实现对该树的前序遍历。

解:

  以向量为存储结构的完全二叉树,其存储在向量中的结点其实是按层次遍历的次序存放的,可以根据课本第74页的内容设计出算法:

 typedefcharDataType;//设结点数据类型为char

 #defineM100//设结点数不超过100

 typedefDataTypeBinTree[M];

 voidPreorder(BinTreeT)

  {//前序遍历算法

   intn=T[0];

   intp[M];//设置一队列存放结点值

   inti,j;

   for(i=1;i<=n;i++)

    {

     if(i==1)//根结点

       j=1;

     elseif(2*j<=n)//左子树

         j=2*j;

       elseif(j%2==0&&j

           j=j+1;

         elseif(j>1)//双亲之右兄弟

            j=j/2+1;

     p[i]=T[j];//入队

     printf("%c",p[i]);//打印结点值

    }

  }

10.以线索链表作为存储结构。

分别写出在前序线索树中查找给定结点*p的前序后继,以及在后序线索树中查找*p的后序前趋的算法。

解:

  算法如下:

 BinThrNode*SearchPostInPre(BinThrNode*p)

  {//查找结点*p的前序后继

   if(p)

    {

     if(p->rtag==Link)&&(p->ltag==link)//当左、右都为孩子指针

      returnp->lchild;//*p的前序后继为左孩子

     elsereturnp->rchild;

    }

  }

 BinThrNode*SearchPreInPost(BinThrNode*p)

  {//查找*p结点的后序前趋

   if(p)

    {

     if(p->ltag==thread)||(p->rtag==thread)//当有左线索或无有孩子

       returnp->lchild; //*p的后续前趋为p->lchild

     elsereturnp->rchild;

    }

  }

习题精选

一、.单项选择题

1.把一棵树转换为二叉树后,这棵二叉树的形态是()。

A.唯一的B.有多种

C.有多种,但根结点都没有左孩子D.有多种,但根结点都没有右孩子

2.由3个结点可以构造出多少种不同的二叉树?

()

A.2B.3C.4D.5

3.一棵完全二叉树上有1001个结点,其中叶子结点的个数是()。

A.250B.500C.254D.501

4.一个具有1025个结点的二叉树的高h为()。

A.11B.10C.11至1025之间D.10至1024之间

5.深度为h的满m叉树的第k层有()个结点。

(1=

A.mk-1B.mk-1C.mh-1D.mh-1

6.利用二叉链表存储树,则根结点的右指针是()。

A.指向最左孩子B.指向最右孩子C.空D.非空

7.对二叉树的结点从1开始进行连续编号,要求每个结点的编号大于其左、右孩子的编号,同一结点的左右孩子中,其左孩子的编号小于其右孩子的编号,可采用()遍历实现编号。

A.先序B.中序C.后序D.从根开始按层次遍历

8.若二叉树采用二叉链表存储结构,要交换其所有分支结点左、右子树的位置,利用()遍历方法最合适。

A.前序B.中序C.后序D.按层次

9.在下列存储形式中,()不是树的存储形式?

A.双亲表示法B.孩子链表表示法C.孩子兄弟表示法D.顺序存储表示法

10.一棵树高为K的完全二叉树至少有(C)个结点

A.2k–1B.2k-1–1C.2k-1D.2k

11.已知一棵二叉树的前序遍历结果为ABCDEF,中序遍历结果为CBAEDF,则后序遍历的结果为(A)。

A.CBEFDAB.FEDCBAC.CBEDFAD.不定

12.二叉树的先序遍历和中序遍历如下:

先序遍历:

EFHIGJK;中序遍历:

HFIEJKG。

该二叉树根的右子树的根是:

(C)

A、EB、F C、G D、H

13.一棵非空的二叉树的先序遍历序列与后序遍历序列正好相反,则该二叉树一定满足(C)

A.所有的结点均无左孩子B.所有的结点均无右孩子

C.只有一个叶子结点D.是任意一棵二叉树

14.n个结点的线索二叉树上含有的线索数为(C)

A.2nB.n-lC.n+lD.n

15.在下述结论中,正确的是(D)

①只有一个结点的二叉树的度为0;

②二叉树的度为2;

③二叉树的左右子树可任意交换;

④深度为K的完全二叉树结点个数小于或等于深度相同的满二叉树。

A.①②③B.②③④C.②④D.①④

16.设森林F中有三棵树,第一,第二,第三棵树的结点个数分别为M1,M2和M3。

与森林F对应的二叉树根结点的右子树上的结点个数是(D)。

A.M1B.M1+M2C.M3D.M2+M3

17.首先访问结点的左子树,然后访问该结点,最后访问结点的右子树,这种遍历称为(C)

A.前序遍历B.后序遍历C.中序遍历D.层次遍历

18.在一棵高度为k的满二叉树中,结点总数为(C)

A.2k-1B.2kC.2k-1D.log2k+1

19.在由4棵树组成的森林中,第一、第二、第三和第四棵树中的结点个数分别为30,10,

20,5,当把森林转换成二叉树后,对应的二叉树中根节点的左子树中结点个数为(B)。

A.64B.29C.30D.4

20.在一棵度数为4的树T中,若有20个度为4的结点,10个度为3的结点,1个度为2的结点,10个度为1的结点,则树T的叶结点个数是(B)

A.41B.82C.113D.122

21.已知一棵完全二叉树的第6层(设根为第1层)有8个叶结点,则该完全二叉树的结点个数最多是(C)

A.39B.52C.111D.119

22.若一棵完全二叉树有768个结点,则该二叉树中叶结点的个数是(C)

A.257B.258C.384D.385

23.若一棵二叉树的前序遍历序列和后序遍历序列分别是1,2,3,4和4,3,2,1,同该二叉树的中序遍历列不会是(C)

A.1,2,3,4B.2,3,4,1C.3,2,4,1D.4,3,2,1

24.将森林转换为对应的二叉树,若在二叉树中,结点u是结点v的父结点的父结点,则在原来的森林中,u和v可能具有的关系是(B)

I.父子关系II.兄弟关系III.u的父结点与v的父结点是兄弟关系

A.只有IIB.I和IIC.I和IIID.I、II和III

25.已知一棵有2011个结点的树,其叶结点的个数为116,该树对应的二叉树中无右孩子的结点个数是(D)

A.115B.116C.1895D.1896

26.对n(n>=2)个权值均不相同的字符构成赫夫曼树,关于该树的叙述中,错误的是(A)

A.该树一定是一棵完全二叉树

B.树中一定没有度为1的结点

C.树中两个权值最小的结点一定是兄弟结点

D.树中任一非叶结点的权值一定不小于下一层任一结点的权值

27.一棵非空的二叉树的先序遍历序列与后序遍历序列正好相反,则该二叉树一定满足()。

A.所有的结点均无左孩子B.所有的结点均无右孩子

C.只有一个叶子结点D.是任意一棵二叉树

28.某二叉树的前序序列和后序序列正好相反,则该二叉树一定是()的二叉树。

A.空或只有一个结点B.任一结点无左子树

C.高度等于其结点数D.任一结点无右子树

29.若X是二叉中序线索树中一个有左孩子的结点,且X不为根,则X的前驱为()。

A.X的双亲B.X的右子树中最左的结点

C.X的左子树中最右结点D.X的左子树中最右叶结点

30.引入二叉线索树的目的是()。

A.加快查找结点的前驱或后继的速度B.为了能在二叉树中方便的进行插入与删除

C.为了能方便的找到双亲D.使二叉树的遍历结果唯一

31.线索二叉树是一种()结构。

A.逻辑B.逻辑和存储C.物理D.线性

32.设F是一个森林,B是由F变换得的二叉树。

若F中有n个非终端结点,则B中右指针域为空的结点有()个。

A.n-1B.nC.n+1D.n+2

二、应用题

1.设一棵二叉树的先序、中序遍历序列分别为

先序遍历序列:

ABDFCEGH中序遍历序列:

BFDAGEHC

(1)画出这棵二叉树。

(2)将这棵二叉树转换成对应的树(或森林)。

【解】

 

2.将下面的森林变换成二叉树。

 

3.假设某密文仅有8个字母C1,C2,.....C7,C8组成,各个字母在电文中出现

的频率分别为5,25,3,6,10,11,36,4,试回答以下问题:

(1)构造出相对应的哈夫曼树。

(2)写出该8个字母的哈夫曼编码。

(3)试计算该哈夫曼树的带权路径长度。

4.已知A[1..N]是一棵顺序存储的完全二叉树,如何求出A[i]和A[j]的最近的共同祖先?

【解】根据顺序存储的完全二叉树的性质,编号为i的结点的双亲的编号是i/2,故A[i]和A[j]的最近公共祖先可如下求出:

while(i/2!

=j/2)

if(i>j)i=i/2;elsej=j/2;

退出while后,若i/2=0,则最近公共祖先为根结点,否则最近公共祖先是i/2。

5.已知一棵满二叉树的结点个数为20到40之间的素数,此二叉树的叶子结点有多少个?

【解】结点个数在20到40的满二叉树且结点数是素数的数是31,其叶子数是16。

6.假设一棵二叉树的层次序列为ABCDEFGHIJ,中序序列DBGEHJACIF。

请画出这棵二叉树。

【解】按层次遍历,第一个结点(若树不空)为根,该结点在中序序列中把序列分成左右两部分—左子树和右子树。

若左子树不空,层次序列中第二个结点左子树的根;若左子树为空,则层次序列中第二个结点右子树的根。

对右子树也作类似的分析。

层次序列的特点是:

从左到右每个结点或是当前情况下子树的根或是叶子。

 

三、算法设计题

1.以二叉链表作为二叉树的存储结构,编写交换二叉树每个结点的左孩子和右孩子的算法。

voidChangeLR(BiTree&T)

{

BiTreetemp;

if(T->lchild==NULL&&T->rchild==NULL)

return;

else

{

temp=T->lchild;

T->lchild=T->rchild;

T->rchild=temp;

}

ChangeLR(T->lchild);

ChangeLR(T->rchild);

}

2.以二叉链表作为二叉树的存储结构,计算二叉树最大的宽度(二叉树的最大宽度是指二叉树所有层中结点个数的最大值)。

[题目分析]求二叉树高度的算法见上题。

求最大宽度可采用层次遍历的方法,记下各层结点数,每层遍历完毕,若结点数大于原先最大宽度,则修改最大宽度。

intWidth(BiTreebt)//求二叉树bt的最大宽度

{if(bt==null)return(0);//空二叉树宽度为0

else

{BiTreeQ[];//Q是队列,元素为二叉树结点指针,容量足够大

front=1;rear=1;last=1;//front队头指针,rear队尾指针,last同层最右结点在队列中的位置

temp=0;maxw=0;//temp记局部宽度,maxw记最大宽度

Q[rear]=bt;//根结点入队列

while(front<=last)

{p=Q[front++];temp++;//同层元素数加1

if(p->lchild!

=null)Q[++rear]=p->lchild;//左子女入队

if(p->rchild!

=null)Q[++rear]=p->rchild;//右子女入队

if(front>last)//一层结束,

{last=rear;

if(temp>maxw)maxw=temp;//last指向下层最右元素,更新当前最大宽度

temp=0;

}//if

}//while

return(maxw);

}//结束width

3.以二叉链表作为二叉树的存储结构,用按层次顺序遍历二叉树的方法,统计树中具有度为1的结点数目。

i

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 人文社科 > 教育学心理学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1