04-树
1.学习总结
1.1树结构思维导图
1.2 树结构学习体会
树相较于之前学习的,最大的区别就是,它可以有多个后继,很大一个特点就是操作时频繁出现递归,如果懂这段代码会觉得利用递归代码精简很多,但是不能看出代码功能的话,就比较难理解中间是怎么操作的。树的知识点也很多,光是遍历,就有先序后序中序层次遍历好几种,相应的有些方面功能也很强大,可以解决很多实际问题,比如哈夫曼树—修理牧场,交并集—朋友圈
2.PTA实验作业
2.1 题目1:7-8 jmu-ds-二叉树叶子结点带权路径长度和
2.2 设计思路
定义字符串数组str,树bt,变量i,叶子结点带权路径长度和n,设n初值为0
输入str
求str长度len
利用递归构造树bt
若当前位置的字符str[i]为#,该结点为NULL
否则 将该字符赋给bt结点
该结点高度为log(i)/log(2)+1
根据二叉树顺序储存结点关系
2i位置元素构成bt结点的左孩子
2i+1位置元素构成bt结点的右孩子
若树不为空
访问叶子结点,n累加该结点的值与其高度的乘积
访问左子树的叶子结点,n累加该节点的值与其高度的乘积
访问左子树的叶子结点,n累加该节点的值与其高度的乘积
输出n
2.3 代码截图
2.4 PTA提交列表说明。
求叶子结点带权路径长度和需要实现俩部分内容:
(1)找到叶子结点,利用递归,找到左右节点皆空的结点
(2)知道这些叶子结点的高度
1.遇到的主要问题是第二个,如何求某个结点的高度,只学习过求树的高度。我们知道高度为H的树,节点数i最大为2^H-1,解出来H=log(i)/log(2)+1。将高度也加入树的结构体中,方便后面计算操作。
2.调用树的构造函数传参时,i传入的是1,一定要给它赋值,否则输出为0,调试会发现不会执行那些递归构造语句,自然长度和为0了,赋值为1,是因为第一个字符,也就是str数组中str[0]位置元素#不是结点
2.1 题目2:7-7 朋友圈
2.2 设计思路
定义总人数sn,俱乐部数cn,数组t[n]代表所有人的序号,ans,用-ans表示朋友圈人数
输入sn,cn
将数组t所有值初始化为-1,代表各自所属的集合
当cn--不为0时,执行下列循环语句
输入该俱乐部的人数sum
输入根x
当sum--不为0时,执行循环语句
输入成员y
将x,y合并
查找x,y集合编号fx,fy
如果二者相等,已经在一个集合了,return
如果不等
x,y划入一个集合
t[fx]变为t[fx]和t[fy]之和
fy的集合编号变为fx
找出最小的t[fx],赋给ans
cn为0时循环结束
输出-ans
思路通俗版:
所有人的t初值为-1,a,b在一个朋友圈,设a为根,a,b在一个朋友圈,将a,b合并,t[a]=-1,t[b]=-1,将它们合并的值
赋给t[a],t[a]变为-2,t[b]变为a的序号,t[a]=-2代表朋友圈内有俩个人,继续将t[]值为负值的与根相合并,因为学生编号从1开始,t[]值为正的都已经找到相应集合了。所以可以通过找最小的t[]值,它的绝对值代表最大的朋友圈数。
2.3 代码截图
2.4 PTA提交列表说明。
知识点:朋友圈主要是利用交并集,将朋友关系的元素合并到一个集合
错误:忽略了如果每个俱乐部都不超过一个成员的情况,因为同俱乐部才有可能存在朋友关系
改正:判断每个俱乐部的人数,如果都不超过一个,最大的朋友圈即为1
2.1 题目3:6-4 jmu-ds-表达式树
2.2 设计思路
构建表达式树:
定义栈 q存储数字
定义栈 op存储运算符
将#入栈op
遍历字符串str
如果str[i] 为数字
创建节点T
将str[i]的值赋给T并置左右孩子为空
将T入栈q
如果str[i]为运算符
调用Precede函数,判断op栈顶元素与str[i]的优先级大小
如果栈顶元素优先级小
将运算符入栈op;
如果优先级一样大
将op栈顶元素出栈
如果栈顶元素优先级大
创建新的节点T
出栈op栈顶元素
并将栈顶元素的值赋给T
取q栈顶元素赋给T的右孩子再出栈栈顶元素
取q栈顶元素赋给T的左孩子再出栈栈顶元素
如果栈op中仍有运算符
创建新的节点T
出栈op栈顶元素
并将栈顶元素的值赋给T
取q栈顶元素赋给T的右孩子再出栈栈顶元素
取q栈顶元素赋给T的左孩子再出栈栈顶元素
计算表达式树:
定义变量a b 存储运算数;
递归遍历树
把所有字符转换成数字;
a,b分别存储T节点的左右子树;
判断T值即运算符
如果为+号,计算a+b的值,并返回
如果为-号,计算a-b的值,并返回
如果为*号,计算a*b的值,并返回
如果为/号
如果b为0,输出divide 0 error!
如果不为0,计算a/b的值,并返回
2.3 代码截图
2.4 PTA提交列表说明。
错误:非零返回
修改:输出结果多出一个0,将return 0改为exit(0)后正确
return 0和exit(0)的区别:return 0是返回函数调用,如果返回的是main函数,则为退出程序;exit(0)是在调用时强行退出程序
3.截图本周题目集的PTA最后排名
3.1 PTA排名
3.2 我的得分:2.5分
4. 阅读代码
优先队列:[https://blog.csdn.net/wyk1823376647/article/details/52048896]
代码地址:[https://blog.csdn.net/gdg_dys/article/details/60477022]
代码功能:7-7修理牧场
代码优点:
用优先队列这一条语句就可以实现队列元素按从大到小,小的优先出队,代码精简了很多,思路也很巧妙,将木头锯成俩段,再将长的那段锯成俩段,重复操作,累加每一次被锯木头的长度,如何让累加值最小,也就需要保证每次锯的木头是由较小的俩根组成,这也就是哈夫曼树的构造原理,转而构造哈夫曼树
5. 代码Git提交记录截图