一、本章重点
1. 二叉树的四种遍历方式代码:先、中、后序遍历(递归)+层次遍历。其中层次遍历利用队列操作,可以运用STL模板。加深了把“栈和队列”作为辅助工具的思想。
2. 常用的树的表示方法有:双亲表示法;孩子表示法;孩子兄弟法。同时前两种可以结合。总之,根据不同应用场景来,不一定按照书本的结构。
其中孩子兄弟法可以转化为二叉树,用二叉树的各种操作。
3. 森林与二叉树的转换;树和森林的遍历
4. 哈夫曼树:如何构建一棵哈夫曼树;最优树不一定是哈夫曼树;哈夫曼树编码(存储+解码的优势)
5. 编程题:求二叉树的叶子结点个数;List Leaves;最深的叶子;树的同构
二、打代码收获
1. if-else逻辑问题:如图来自题目 List Leaves。写法一过关,写法二不过关
写法一与写法二的逻辑不同。
解释:
看黄色的笔迹。框住的相当于{},明显发现第二种写法中的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)
3.bool *check = new bool[n]();
不确定数组元素个数时,建议动态分配数组。同时记得delete[ ] check;【delete[ ] 数组名;】
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. 堆是一种经过排序的完全二叉树
最小堆、最大堆的概念