zoukankan      html  css  js  c++  java
  • 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 学习体会

    • 在解题时,不要固性思维,可以多想想新的解题思路。
    • 可以通过学习别人的优秀代码,来扩宽自己的解题思路。有时候做题可能就会有意想不到的收获。
  • 相关阅读:
    POJ 1003 解题报告
    POJ 1004 解题报告
    POJ-1002 解题报告
    vi--文本编辑常用快捷键之光标移动
    常用图表工具
    September 05th 2017 Week 36th Tuesday
    September 04th 2017 Week 36th Monday
    September 03rd 2017 Week 36th Sunday
    September 02nd 2017 Week 35th Saturday
    September 01st 2017 Week 35th Friday
  • 原文地址:https://www.cnblogs.com/Lay-549/p/10781246.html
Copyright © 2011-2022 走看看