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直接返回宽度。