第五章树和二叉树学习小结

一、本章重点

1. 二叉树的四种遍历方式代码:先、中、后序遍历(递归)+层次遍历。其中层次遍历利用队列操作,可以运用STL模板。加深了把“栈和队列”作为辅助工具的思想。

2. 常用的树的表示方法有:双亲表示法;孩子表示法;孩子兄弟法。同时前两种可以结合。总之,根据不同应用场景来,不一定按照书本的结构。

其中孩子兄弟法可以转化为二叉树,用二叉树的各种操作。

第五章树和二叉树学习小结_第1张图片第五章树和二叉树学习小结_第2张图片

 

 

 第五章树和二叉树学习小结_第3张图片

3. 森林与二叉树的转换;树和森林的遍历

4. 哈夫曼树:如何构建一棵哈夫曼树;最优树不一定是哈夫曼树;哈夫曼树编码(存储+解码的优势)

5. 编程题:求二叉树的叶子结点个数;List Leaves;最深的叶子;树的同构


 

二、打代码收获

1. if-else逻辑问题:如图来自题目 List Leaves。写法一过关,写法二不过关

第五章树和二叉树学习小结_第4张图片

 

 

写法一与写法二的逻辑不同。

解释:

看黄色的笔迹。框住的相当于{},明显发现第二种写法中的4语句前多了else。

  写法一的执行情况:执行1;执行2;执行1、2;不执行1、2

  写法二的执行情况:执行3;执行4;不执行3、4

 

2. List Leaves 查根结点方法  [链接(笔者才能打开):https://pintia.cn/problem-sets/1257617654157504512/problems/1257617877101514752]

【ps:树的结点是顺序存储(数组),编号0-N-1;输入数据是结点个数N + 每个结点的左右孩子下标;查根结点】

隐藏信息:根结点不是任何一个结点的孩子,所以在所有结点的孩子中,哪个编号没出现,哪个编号对应的就是根结点。

查根结点方法:利用 “bool check[n] = {false};”, 在接受数据构建树时,每接受一个孩子下标,就更新check:check [孩子下标] = true;最后遍历check,值为false的check此时的下标就是根结点下标。

 

收获:一开始想着的是构建完这棵树之后,再从0到N-1遍历整棵树的孩子下标,找到根结点,但是这个方法就比我之前想的方便多了。

 

3.  对输出的要求:输出的数据之间有空格,但同时最后一个不能有空格。之前常常因为这个而烦恼。

可以利用一些小技巧:如更新变量内容。

如:(来自List Leaves)

第五章树和二叉树学习小结_第5张图片

 

 

 

3.bool *check = new bool[n]();

不确定数组元素个数时,建议动态分配数组。同时记得delete[ ] check;delete[ ] 数组名;

第五章树和二叉树学习小结_第6张图片

 

4. 使用STL,注意头文件#include/...

5. 题目:树的同构 

[链接(谁都可以打开):https://pintia.cn/problem-sets/988034414048743424/problems/988039710297038848]

[链接(笔者才能打开):https://pintia.cn/problem-sets/1257617654157504512/problems/1257617809174761472]

重点:递归;全局变量。

思考过程:题目没有告诉我们换哪个结点的孩子,我们怎么去判断是否同构呢?实在想不明白这个题目的意思---百度---找到以下两个比较好的:

1)慕课讲解:https://www.icourse163.org/learn/ZJU-93001?tid=1002654021#/learn/content?type=detail&id=1003620985&cid=1004311366

2)CSDN:https://blog.csdn.net/qq_40883132/article/details/80041817

 

 

 看完了之后有种似懂非懂的感觉,原来需要我们去判断是否换了孩子,再进一步判断重构。2)中,对于根结点的判断能理解,但是后面的就不明白为什么了---于是我去看了慕课视频,然后把所有情况列了出来(太多了),然后再根据上面的讲解的启发,我尝试写出了下面的代码:

bool Isomorphic(int R1,int R2)
{//利用根结点判断T1,T2是否同构 
    if(R1==NUll&&R2==NUll)
    //如果T1,T2都为空树---同构 
      return 1; 
      
    else if(R1!=NUll&&R2!=NUll&&T1[R1].letter!=T2[R2].letter)
    //如果T1,T2都不为空树,且根结点内容不相等---不同构 
      return 0;
      
    else if(R1!=NUll&&R2!=NUll&&T1[R1].letter==T2[R2].letter)
    {//如果T1,T2都不为空树,且根结点内容相等---继续判断T1,T2左右子树 
        if(T1[R1].lchild==NUll&&T2[R2].lchild==NUll) 
        //如果T1,T2的左子树都为空,那么递归看右子树是否同构 
          return Isomorphic(T1[R1].rchild,T2[R2].rchild);
        if(T1[R1].lchild!=NUll&&T2[R2].lchild!=NUll&&T1[T1[R1].lchild].letter==T2[T2[R2].lchild].letter) 
        //如果T1,T2的左子树都不为空,且左子树的根结点内容相等,判断左右子树是否同构 
          return Isomorphic(T1[R1].lchild,T2[R2].lchild)&&Isomorphic(T1[R1].rchild,T2[R2].rchild);
        else
        /*T1左子树空、T2左不空 or T1左不空、T2左空 
        or  T1,T2的左都不空,但左子树的根结点内容不等---判断T1左与T2右&&T1右与T2左是否同构 
        */ 
          return  Isomorphic(T1[R1].lchild,T2[R2].rchild)&&Isomorphic(T1[R1].rchild,T2[R2].lchild);
    }
    
    else
    //如果一棵树空,一棵树不空---不同构
      return 0; 
}

虽然很复杂,还需要优化,但是没想到我过了!(这期间在“空树”的测试点那里出了点问题,不过解决了)

这里的函数由于需要用到T1,T2,所以就定义T1,T2为全局变量。

6. 题目:最深叶子结点。没想到利用层次遍历就可以解决问题了。

[链接(笔者才能打开):https://pintia.cn/problem-sets/1263645703563206656/problems/1263645795540099072]

 


三、其他

1. 二叉搜索树  与  二叉线索树  不同。

二叉搜索树(又二叉查找树,二叉排序树):

若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。

构建二叉搜索树:https://blog.csdn.net/danwuxie/article/details/81025672

2. 堆是一种经过排序完全二叉树

最小堆、最大堆的概念

你可能感兴趣的:(第五章树和二叉树学习小结)