c#二叉树 取叶子节点个数_二叉树遍历的应用总结(附代码)

写在前面的一些废话

    我个人最近有点忙,因此很久都没更新了。不过终于和老师确定了开题的方向,临时更换研究方向还是有点难的,之前搞图像算法的心血全都白费,重新准备其他方向的开题算法,心里还是有点慌,有点不知所措的。还有几天时间,选择相信自己吧。

        同时,也因此最近很多小伙伴问我问题都没怎么回复,望谅解,等开题结束稍微轻松一点再解答你们的问题的。还有一点就是,希望大家真的不要私聊我问问题,每次都在重复回答你们的问题真的还是有点心累的,有时也会有点生气,所以希望大家有问题就在群里问。并且我们已经分享了很多经验和院校信息在本公众号以及群里面了,有些同学还在问院校信息,甚至还在问考试科目是什么,我真的无能为力,你们自己都不对自己负责我能怎么办?我后期也会专门总结一篇常见的问题汇总的文章,希望能帮助到你们。

    祝自己好运,各位加油!

在开始介绍具体的遍历应用之前,我们先总结一下前面介绍的 3种递归遍历算法 。3种遍历算法的基本思路都是通过将一个大问题化解为两个小问题进行求解,从而实现递归遍历。下面我们开始介绍二叉树遍历的应用。

一应用1:求节点个数

假设 二叉树采用二叉链存储结构 存储 ,设一个算法,计算一棵给定二叉树的所有节点个数。

算法思路:与二叉树的遍历类似,我们以后序遍历为例,首先递归遍历左子树和右子树,然后访问根节点,在递归的同时进行计数。因此,计算一棵二叉树b 中所有节点个数的递归模型f(b) 如下:

f(b)=0  若b=NULLf(b)=f(b->lchild)+f(b->rchild)+1 其他
代码 :对应的递归算法如下:
int Nodes(BTNode *b){  int num1,num2;    if (b==NULL)        return 0;    else        return Nodes(b->lchild)+Nodes(b->rchild)+1 ///先左子树、再右子树,最后根节点(计1)}
二应用2:求叶子节点个数

假设二叉树采用二叉链存储结构 存储 ,设计 一个算法,计算一棵给定二叉树的 所有叶子节点个数 。

算法思路:遍历方法与计算所有节点类似,最终计算一棵二叉树b中所有叶子节点个数的递归模型f(b)可以表示为:

f(b)=0   若b=NULLf(b)=1   若*b 为叶子节点f(b)=f(b->lchild)+f(b->rchild) 其他情况
代码 : 对应的递归算法如下:
int LeafNodes(BTNode *b){ int num1,num2;    if (b==NULL)        return 0;    else if (b->lchild==NULL && b->rchild==NULL)        return 1;    else //先左子树、再右子树,最后根节点(计0)        { num1=LeafNodes(b->lchild);          num2=LeafNodes(b->rchild);          return (num1+num2);        }}
三应用3 : 二叉树的复制

 假设二叉树采用二叉链存储结构,设计一个算法把二叉树b 复制到二叉树t中。

算法思路:如下图所示,我们采用先序遍历的方法,依次访问左边链表中的元素,并将其按照先序遍历的方法存储到新的链表t中的相应位置,这样便完成了二叉树的复制。

0db92b5d224f5a376aca48354d021374.png

其递归模型如下:
f(b,t) : t=NULL                  若b=NULLf(b,t) :复制根节点*b 产生*t 节点;   其他 情况    f(b->lchild,t->lchild);    f(b->rchild,t->rchild);
代码 :对应的递归算法如下:
void Copy(BTNode *b,BTNode *&t){ if (b==NULL) t=NULL;  else //先根节点、再左子树,最后右子树,  { t=(BTNode *)malloc(sizeof(BTNode));    t->data=b->data; // 复制一个根节点*t    Copy(b->lchild,t->lchild); // 递归复制左子树    Copy(b->rchild,t->rchild); ; // 递归复制右子树  }}
四应用4:二叉树的左右子树交换

设二叉树采用二叉链存储结构,设计一个算法把二叉树b 的左、右子树进行交换。要求不破坏原二叉树 。

解题思路:要求不破坏原有二叉树,实际上就是建立一个新的二叉树t ,它交换了二叉树b 的左、右子树。

其递归模型如下:
f(b,t) : t=NULL                              若b=NULLf(b,t) : 复制根节点*b 产生*t 节点;      其他 情况    f(b->lchild,t->rchild);    f(b->rchild,t->lchild);
代码 :对应的递归算法如下:
void Swap(BTNode *b,BTNode *&t){ if (b==NULL) t=NULL;  else    { t=(BTNode *)malloc(sizeof(BTNode));      t->data=b->data; // 复制一个根节点*t      Swap(b->lchild,t->rchild); // 递归交换左子树      Swap(b->rchild,t->lchild); // 递归交换右子树}}
五应用5:求指定节点所在层数

假设 二叉树采用二叉链存储结构 , 设计一个算法Level() 求 二叉树b 中值为x 的节点的层次 ( 假设所有节点值唯一 ).

解题思路:设 Level(b , x , h) 返回 二叉树b中 data 值为x 的节点的层次, 其中b 指向根节点,h 表示b 所指节点的层数,初始化为1。当在二叉树b 中找到data 值为x 的节点,返回其层次(一个大于0的整数);若没有找到,返回0。

递归模型f(b ,x , h) 如下:
空二叉树中 找不到值为x 的节点 :•     Level(b , x , h)=0  //若b=NULL若b 指向 值为x 的节点: •    Level(b , x , h)=h // 若b->data=x对于其他情况: : 首先在左子树中找。若找到 了直接返回。•   Level(b,x,h)=l //当l=Level (b->lchild,x,h+1)≠0否则 返回在右子树中的查找结果。•   Level(b,x,h)=Level(b->rchild,x,h+1)// 其他情况
代码 :对应的递归算法如下:
int Level(BTNode *b,ElemType x,int h)// 找到*p 节点后h 为其层次, 否则为0{ if (b==NULL) return 0; // 空树时返回0  else if (b->data==x) return h; // 找到节点时  else    { l=Level(b->lchild,x,h+1); // 在左子树中查找      if (l==0) // 左子树中未找到时在右子树中查找        return Level(b->rchild,x,h+1);      else return l;    }}
六应用6:层次遍历,求逆路径

假设二叉树采用二叉链存储结构,设计一个算法输出下图中从根节点到每个叶子节点的逆路径。

18af1f2e25a047321e66c4749db49bcc.png

解题思路:设计的队列为非环形队列qu ,将所有已访问过的节点指针进队,并在队列中保存双亲节点的位置。

struct snode{ BTNode *node; // 存放当前节点指针int parent; // 存放双亲节点在队列中的位置} qu[MaxSize]; // 定义非环形队列int front = rear = -1; //置队列为空队列

当找到一个叶子节点时,在队列中通过双亲节点的位置输出根节点到该叶子节点的逆路径。(类似于用队列求解迷宫问题)

代码 : 对应算法如下:
void AllPath(BTNode * b){struct snode{BTNode *node;//存放当前节点指针int parent;//存放双亲节点在队列中的位置} Qu[MaxSize];//定义非循环队列int front,rear,p;//定义队头和队尾指针front=rear=-1;//置队列为空队列rear++;Qu[rear].node=b;//根节点指针进队Qu[rear].parent=-1;//根节点没有双亲节点while(front<rear)//队列不为空{front++;//front为当前出队节点的下标b=Qu[front].node;//队头出队if(b->lchild==NULL&&b->rchild==NULL)//*b为叶子节点{printf("%c到根节点逆路径:",b->data);p=front;while(Qu[p].parent!=-1){printf("%c\n",Qu[p].node->data);p=Qu[p].parent;}printf("%c\n",Qu[front].node->data);}if(b->lchild!=NULL)//左孩子进队{rear++;Qu[rear].node=b->lchild;Qu[rear].parent=front;}if(b->rchild!=NULL)//右孩子进队{rear++;Qu[rear].node=b->rchild;Qu[rear].parent=front;}}}

036509774333e1b38994d63e295ad7ef.gif eb08ac285d5de0ed38f0d168a90064ea.gif 512fe905b0a38353c7e81b1700864927.gif

- End -

80870125056ecb0f44ba1ec525f02610.png

点击“❀在看”,让更多朋友们看到吧~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值