DS博客作业05——树

1.本周学习总结(0--2分)

1.思维导图

2.谈谈你对树结构的认识及学习体会。

不同类型的树之间是可以相互转化的,比如一颗普通的树可以通过特定的过程转化成二叉树,也可以转化成森林,反之亦然。
树也存在着多种的存储结构,例如:双亲存储,孩子链存储,孩子兄弟存储
二叉树是最常见的树,我们详细的学历了二叉树的创建、消除等等基本构造二叉树的方法,也学习了如何用先序加中序,中序加后序来进行树的构建。通过二叉树的学习,我们又学习了线索二叉树,和哈夫曼树,这两个知识点都是在二叉树的基础上进行升华的。
线索二叉树可以轻易的得到该结点的相邻的结点,而哈夫曼树则可以用来求解最优解的问题。

2.PTA实验作业(6分)

2.1.根据后序和中序遍历输出先序遍历

本题要求根据给定的一棵二叉树的后序遍历和中序遍历结果,输出该树的先序遍历结果。

2.1.1设计思路(伪代码)

以样例为例

//伪代码(BinTree CreatBt函数)
if n=0 then
    return 0
end if
定义一个BinTree类型的变量BT//构造结点
定义一个int型变量mid//用于储存in数组中,该结点的位置
for i=0 to n do
    if in[i]与post[n-1]相等 then
        将i赋值给mid
        break;
    end if
end for
将post[n-1]的值赋给BT->data
BT->lchild =CreatBt(post,in,mid)//递归创建左孩子
BT->rchild =CreatBt(post+mid,in+1+mid,n-1-mid)//递归创建右孩子

2.1.2代码截图



2.1.3本题PTA提交列表说明。

Q1:一连串的编译错误……快把我搞疯掉
A1:然而,全都是一些基本的错误,比如把写成了;上面结构体写的BTNode,下面定义变量的时候,又写成了TNode之类的。(吐血)
Q2:其实,他提示的错误点,我没看懂

A2:然后,就到编译器上去调试了,结果才发现,我定义的变量mid没赋值,我也传参传的好好的。

2.2 jmu-ds-输出二叉树每层节点

层次遍历树中所有节点。输出每层树节点。
树结构按照树的先序遍历递归建树,比如先序遍历字符串“ABD#G###CEH###F#I##”#代表空节点。

2.2.1设计思路(伪代码)

//设计思路
利用队列,将二叉树按行存入队列中,利用flag,当flag为1时代表,curNode在该行的第一个位置,当flag=0时,依次出队输出,直到curNode与该行的队尾指针lastNode相等时,进入下一行的扫描。
//伪代码(LevelOrder函数)
定义BinTree型的队列qt
定义int型变量level并赋初值为0,用于表示行数;flag并赋初值为1,用于判断是否为每行开头
定义BinTree型变量curNode、lastNode//分别指向当点结点和该行的最后一个结点,并将bt赋值给两个变量
if bt不为空 then
    将bt存入队列qt中
end if
while qt不为空 do
    将队头赋值给curNode
    if curNode的左孩子不为空  then
        将curNode的左孩子入队
    end if
    if curNode的右孩子不为空  then
        将curNode的右孩子入队
    end if
    if flag的值为1 then
        输出“++level:”
    end if
    if curNode与lastNode相等 then
        将qt的队尾的值赋给lastNode
        输出当前结点的值和一个逗号
        将1赋给flag
    else
        if lastNode不等于curNode的左孩子
            输出当前结点的值和一个逗号
        end if
        将0赋给flag
    end if
    将队列的队头出队
end while

2.2.2代码截图



2.2.3本题PTA提交列表说明。

Q1:提交列表显示的是不空的时候出错(有两个不空的测试点),当时测试样例能过,但是并不知道哪里有错。
A1:然后就开始自己编数据,想想各种数据的可能情况,然后就想到一个要是最后一行的叶子结点是上一行结点的左孩子,这个代码好像不能运行出来

结果,事实证明,真的不能……

Q2:然后就针对要是最后一个叶子节点是左孩子的情况进行改进。一运行,测试样例过了,一提交,又是部分正确。。。
A2:然后,疯狂编数据,发现,这么改完以后,有时候最后一个叶子结点会输出两次。
Q3:再次修改,(忘了当时怎么想的,反正一直改,一直调试)最后,我所能想到的数据都过了。开开心心的提交,部分正确。
A3:改不动了,是在是不知道该朝哪个方向进行修正,然后借鉴了同学的思路,发现只要一行到结尾的时候,将队尾的值赋给lastNode就实现了lastNode指向下一行的行末了。

2.3 修理牧场

农夫要修理牧场的一段栅栏,他测量了栅栏,发现需要N块木头,每块木头长度为整数L​i​​ 个长度单位,于是他购买了一条很长的、能锯成N块的木头,即该木头的长度是L​i​​ 的总和。但是农夫自己没有锯子,请人锯木的酬金跟这段木头的长度成正比。为简单起见,不妨就设酬金等于所锯木头的长度。例如,要将长度为20的木头锯成长度为8、7和5的三段,第一次锯木头花费20,将木头锯成12和8;第二次锯木头花费12,将长度为12的木头锯成7和5,总花费为32。如果第一次将木头锯成15和5,则第二次锯木头花费15,总花费为35(大于32)。请编写程序帮助农夫计算将木头锯成N块的最少花费。

2.3.1设计思路(伪代码)

//设计思路
利用有限队列的升序排列,自动将模板长度从小到大排列,每次取出两个最小值,将两个值相加,再存放到队列中,自动排序...直到队列为空。这个过程可以看作是切木板的逆过程。先找出最小的两块拼在一起,然后放回木板堆中,再找出最小的两块木板拼在一起,直至整条木板拼接完成。这样就可以实现木板割据的最小费用。
//伪代码
定义int型变量num1、num2分别用于存放队列中最小的两个数
定义int型变量add用于存放num1、num2的切割费用和,sum用于计算总薪酬,并附sum初值0
定义优先序列q,并将q自动升序排列
for i=0 to n do
    输入number
    将number存入队列q中
end for
while 队列q的长度大于1 do
    将队头的值赋给num1
    将队头出队
    将此时队头的值赋给num2
    将此时的队头出队
    将num1与num2的和赋给add  //逆过程中的最小切割费用
    sum等于sum加上add的值
    将add存入队列q中
end while
输出sum的值

2.3.2代码截图



ps:截图中的注释应该是升序排列,而不是降序排列

2.3.3本题PTA提交列表说明。

Q1:做这道题之前,老师有在交流群里说,这道题用哈弗曼树做的话会运行超时,可以用容器中的优先队列做。
A1:当时还不会优先队列,就想着排序的话,用数组做,再用一个sort函数就可以搞定了,每循环一次,调用一次sort函数。后来想想优先队列有一个好处,就是可以自动排序。然后就想多学一个stl容器也不错,就去找了有限队列的相关知识点。

3、阅读代码(-2--2分)

3.1 玩转二叉树

给定一棵二叉树的中序遍历和前序遍历,请你先将树做个镜面反转,再输出反转后的层序遍历的序列。所谓镜面反转,是指将所有非叶结点的左右孩子对换。这里假设键值都是互不相等的正整数。

输入格式:

输入第一行给出一个正整数N(<=30),是二叉树中结点的个数。第二行给出其中序遍历序列。第三行给出其前序遍历序列。数字间以空格分隔。

输出格式:

在一行中输出该树反转后的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。

输入样例:
7
1 2 3 4 5 6 7
4 1 3 2 6 5 7
输出样例:
4 6 1 7 5 3 2

3.2 解题思路

这道题的解题非常的巧妙,通常人的思路可能是将正常的先序序列求出来,在将其逆序。而这个解题则是采取在层次遍历时,先将其右孩子存入数组中,再将其左孩子存入数组中的做法。

3.3 代码截图


3.4 学习体会

  • 在解题时,不要固性思维,可以多想想新的解题思路。
  • 可以通过学习别人的优秀代码,来扩宽自己的解题思路。有时候做题可能就会有意想不到的收获。
原文地址:https://www.cnblogs.com/Lay-549/p/10781246.html