DS博客作业05--树

1.本周学习总结

1.思维导图

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

    1.通过这周的学习,我学到了有关树的知识,其中个人认为最重要的就是建树,和树的遍历了。这些算法大多是通过递归的算法来实现的。而我个人认为递归是一个难懂的算法,因为它的递归是一层一层的,算完后还需要返回回去,讲真的很难搞懂,要花时间去理解。
    2.在学习中接触最多的就是二叉树了,我学到了许多有关二叉树的性质,像是它的结构啦,还有它的父亲结点,兄弟结点的性质等等。还学到了树还有森林,以及二叉树和他们两者之间的转换。
    3.在树的遍历中,分为很多种,有先序遍历和中序遍历和后续遍历以及层次遍历。也正因为有这么多的遍历,所以也衍生出许多的建树的方法,这些都是需要掌握的。
    4.这次的学习和之前的不一样,难度大多了,因为之前的pta的题目,那些都是代码量大但是比较好理解,但是这次的题目,代码量小,但是理解起来却很困难,就比如书上的代码,那些都是基础的,但是理解起来却要很久,要是没有书上的注释的话,可能要花更长的时间,这次的pta题目有挺多是不会写的,有许多是实在想不出来然后参考参考同学的代码或者网上的代码,但是却看不懂,要完成一题用了很长的时间。
    5.总的来说,这次之所以会觉得学得比较困难,是因为递归的算法不好搞懂,虽然代码量少,但却不易理解,个人认为是刷的题不够多,不过之前有个牵强的想法,就是等把算法搞懂了才去写代码,但是有好多人他们都是在还没搞懂的情况下就去写代码,并从中理解了算法,所以以后不能拖了,不能再给自己拖拉的机会,要学习其他同学在打代码中学到知识。

2.PTA实验作业

2.1.题目1:表达式树

2.1.1设计思路(伪代码)

void InitExpTree(BTree &T, string str)  //建表达式的二叉树
    将'#' 进栈;
    while str[i] then
        if str[i]是数字
           新建p结点
            p->data=str[i++];
            左右孩子置为空;
            p入栈node;
        end if
        else //为运算符 
            调用Precede函数比较op栈顶元素与str[i]大小
            如果函数值为'<'
                str[i]进栈; 
            如果函数值为'='
                出栈;
            如果函数值为'>'   
                取node栈顶元素赋值给a;
                出栈;
                取node栈顶元素赋值给b;
                出栈; 
                CreateExpTree(p,b,a,opchar.top());
                opchar出栈;
                p入栈node;
                i--;
        end else
        i++;        
    end while 
    while 栈node和opchar均不为空 then 
        取node栈顶元素赋值给a;   出栈;
        取node栈顶元素赋值给b;   出栈; 
        CreateExpTree(p,b,a,opchar.top());
        opchar出栈;
        p入栈node;
    end while
    T = p;
double EvaluateExTree(BTree T)//计算表达树
    定义浮点型 a,b;
    if 树不为空
        if 左右孩子均不为空 
            返回 T->data-'0';
        a=EvaluateExTree(T->lchild);
        b=EvaluateExTree(T->rchild);
        判断 T->data
            如果是 '+'
                返回a+b;
            如果是 '-'
                返回 a-b;
            如果是 '*'
                返回 a*b;
            如果是 '/':
                if 除数为0 
                    输出"divide 0 error!";
                    退出;
                end if;
                返回 a/b;  
    end if 

2.1.2代码截图



2.1.3本题PTA提交列表说明

  • Q1:讲真的这题是真的难,一开始是完全没有思路的,所以就参考参考书上的代码,但是太长了不好理解。
  • A1:后来看到有同学已经写出来了,所以有不懂的部分就去问明白,勉勉强强的才打完了。
  • Q2:太粗心了,因为一点点的小错误,让我代码看了大半天,书也看了大半天,到最后实在找不出来哪错了,放到VS上调试。
  • A2:switch语句中忘了break,才会出现错误。讲真的VS确实好用。
  • A3:还有错误就是stack node中,一开始BTree写成了int。
  • A4:没次取栈的元素时几乎是要出栈。

2.2.题目2:二叉树叶子结点带权路径长度和

2.2.1设计思路(伪代码)

typedef struct node
{
    char data;
    struct node *lchild, *rchild;
} tree, *Tree;

int main()//主函数 
    定义字符串 s;
    定义 sum = 0;
    输入 s;
    Tree T;
    T=CreatTree(s, 1);
    CountWPL(sum, T,0);
    输出 sum;
    
Tree CreatTree( string s, int i)//建树函数 
    Tree T;
    if i小于字符串长度 
        if s[i] 为 '#'
            T = NULL;
        end if 
        else
            生成新结点 
            T->data = s[i];
            T->lchild=CreatTree( s, 2 * i);
            T->rchild=CreatTree( s, 2 * i + 1);
    end if 
    else T = NULL;
    return T;

void CountWPL(int &sum, Tree T,int i)//计算结点带权路径长度和 
    if T为空 sum += 0;
    else
        if 左右孩子均非空 
            sum += (T->data - '0')*i;
        CountWPL(sum, T->lchild,i+1);
        CountWPL(sum, T->rchild,i+1);
        end if 

2.2.2代码截图


2.2.3本题PTA提交列表说明

  • Q1:刚开始计算的函数定义为 void CountWPL(int sum, Tree T,int i),发现有错误。
  • A1:后来修改为 void CountWPL(int &sum, Tree T,int i)以做到sum递归中保留前值的作用。这是上课老师讲的,所以就采用了。不然其他方法很麻烦。
  • Q2:有一个小细节没注意到出现错误,放到VS中就发现了。
  • A2:就是T->data是字符型的,是要需要减去‘0’进行转换。

2.3.题目3:根据后序和中序遍历输出先序遍历

2.3.1设计思路(伪代码)

typedef struct node{
	int data;
	Btree lchild;
	Btree rchild;
}BTNode;

int main()//主函数
           定义mid/post数组
           循环变量I,结点数量num
           输入num
           for I=0 to num 输入先后序列
           end  for
           Btree bt=CreateBt(mid,post,num)
           输出Preorder:
	   PrintPreOrder(bt)

Btree CreateBt(int mid[],int post[],int num )//建树函数:
           定义树节点bt并且分配内存
           如果num<=0,返回NULL
           for I=0 to num //寻找根节点在中间序列的位置
                if mid[i]==post[num-1] then 跳出 //寻找到了后跳出记录此时的I值
           end  for
           调用递归和I的值 根据关系,建立左右子树
           lchild = CreateBt(mid,post,i)
           rchild = CreateBt(mid+i+1,post+i,num-i-1)
           bt->data=post[num-1]//根节点赋值 
           树建好后返回bt

2.3.2代码截图


2.3.3本题PTA提交列表说明

  • Q1:写这题的时候写完运行一下有个很明显的错误,自己就进行了更改。
  • A1:就是把先序序列和后序序列搞反了。输入的时候以为先读入中序列,后读入后序列
  • Q2:这个问题真的很头疼,实在不懂,就是这个

    里面的创建右孩子的形参为什么要这样写我搞了很久。
  • A2:这种东西我是肯定理解不来,所以就去问其他的同学,最后才理解过来。

3.阅读代码

3.1 题目:求二叉树的宽度

3.2 解题思路

levelnumber函数利用数组a并用高度h作为下标实现了每个高度的结点求和也就是二叉树每一层的宽度,再利用fun函数中调用levelnumber函数取得数组a,接着在数组a中取最大值并返回,完成求二叉树宽度的功能。

3.3 代码截图

3.4 学习体会

  • 因为这道题在上次考试中出现,所以网上找了这段代码,这题我考试的时候没来得及就没写了,不过当时看这题的时候觉得这题应该挺简单的,但是实在没办法,在有原题目还没写的情况下我实在不想冒险去写还没接触的题目,个人认为上述代码容易理解,fun直接返回宽度。
原文地址:https://www.cnblogs.com/wcrbailun/p/10886860.html