第五章学习小结

第五章学习了二叉树。比较重要的两点是由森林到树的转化,通过孩子兄弟法,即左节点连接孩子,右节点连接兄弟节点的方式,可以将森林化成一棵二叉树。二叉树的特点——只有两个子节点,是哈夫曼树应用的重要前提。所以我认为通过把森林化成二叉树,使得需要处理的数据可以通过哈夫曼树的方法进行处理得到最优的结果是很棒的处理方式。哈夫曼树是一种数据最优的存储方式,又称最优树,从结果上看哈夫曼树的构造结果是带权路径最小的树,因此被广泛的应用。

另外再分享下自己做同构树的解题过程吧。

题目给出的关键点是“如果两棵树可以通过若干次左右孩子互换就变成另一棵树,则我们称两棵树是“同构”的。”,从这句话我们可以理解成两棵同构树任意节点对应的父节点都相同。再从这个思路出发,我最初的构想是通过统计,每个节点对应的孩子值之和来比较,这样会非常简单。因为两棵树同一节点对应的孩子节点都是相同的,那么孩子节点所含信息的值之和必定相同,这种做法可以避开很多麻烦。我用层次便利的方法存储了每一个节点的孩子值之和,但是最后再比对的时候发现有的地方对不上。经过思考之后发现,孩子值之和相同并不一定代表孩子相同,就像a+b=c+d并不能推出a=b,c=d这样。于是我只好换一种思路,最终采用了递归的方法逐步解决问题。由最简单的情况入手。第一步——空树,这一步只需要将两次输入的n值进行比较,如果两次输入的n值都为0那么就可以推出两棵树皆为空树皆为同构树。如图,通过传值调用取回n值就好了。然后进入第二步,比较,树不为空,那么先比较根节点的名字,若名字不同则不为同构树。否则进入第三步,既然前面的都符合了,那么先判断是否有一边的节点都为空,这种情况是为了优化处理,如果有则直接比较另一半边的节点。若没有则进入第四步,判断是否有某一边的节点不为空且都相等,这种情况下只需要比较另一半边的节点,如果还是不符合,那么进入最后的步骤——分别比较节点的左右节点。这一块只需要用递归调用实现就好了

int check(node ta[], node tb[], int a, int b)
{
    if (ta[a].name != tb[b].name)return 0;//若名字不同则不为同构树
    if (ta[a].lch == -1 && tb[b].lch == -1)return (check(ta, tb, ta[a].rch, tb[b].rch));//若左结点都为空则直接比较右结点
    if ((ta[a].lch != -1 && tb[b].lch != -1) && (ta[ta[a].lch].name == tb[tb[b].lch].name))return (check(ta, tb, ta[a].rch, tb[b].rch) && check(ta, tb, ta[a].lch, tb[b].lch));//若左结点不为空且都相等,则分别比较左右结点
    else return(check(ta, tb, ta[a].rch, tb[b].lch) && check(ta, tb, ta[a].lch, tb[b].rch));//若上述情况都不满足则分别比较左右结点
}

 

posted @ 2019-05-04 21:01  CharlesKassel  阅读(125)  评论(1编辑  收藏  举报