• 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 学习体会

    • 在解题时,不要固性思维,可以多想想新的解题思路。
    • 可以通过学习别人的优秀代码,来扩宽自己的解题思路。有时候做题可能就会有意想不到的收获。
  • 相关阅读:
    [译]Vulkan教程(03)开发环境
    [译]Vulkan教程(02)概况
    [译]Vulkan教程(01)入门
    CSharpGL(57)[译]Vulkan清空屏幕
    CSharpGL(56)[译]Vulkan入门
    CSharpGL(55)我是这样理解PBR的
    CSharpGL(54)用基于图像的光照(IBL)来计算PBR的Specular部分
    [译]背景:着色的物理和数学(4)
    [译]背景:着色的物理和数学(3)
    [译]背景:着色的物理和数学(2)
  • 原文地址:https://www.cnblogs.com/Lay-549/p/10781246.html
Copyright © 2020-2023  润新知