1.本周学习总结#
1.思维导图##
2.谈谈你对树结构的认识及学习体会。##
相比前面的内容,树的学习难度加大了。树包括孩子结点、兄弟结点、双亲结点,树的遍历顺序有先序遍历、中序遍历、后序遍历、层次遍历。可以根据先序遍历和中序遍历或中序遍历和后序遍历来还原树,转换成代码就需要找一下其中的规律。
树中哈夫曼树的带权路径长度达到最小,也叫最优二叉树。哈夫曼树的建立要把权值较小的结点放较下层,权值较大的结点要越靠近根结点。
树的应用与递归密切相关,所以我们要捋清递归的规则,知道它的执行原理,才能应用递归来解决问题。一级级调用,再一级级返回。
2.PTA实验作业#
2.1.题目1:6-4 jmu-ds-表达式树##
2.1.1设计思路(伪代码)###
void InitExpTree(BTree &T,string str) //建表达式的二叉树
定义栈s存放数字
定义栈op存放运算符
先将‘#’进op栈
while(str[i])
{
if str[i]是数字
T=new BiTNode;
T->data=str[i++];
T的左右孩子置为NULL
T进栈s
else
调用Precede函数比较op栈顶元素与str[i]大小
如果函数值为'<'
str[i]进op栈
如果函数值为'='
op栈出栈
如果函数值为'>'
str[i]进op栈
T=new BiTNode;
op栈顶元素赋值给T->data
T->rchild=s.top();
s栈出栈
T->lchild=s.top();
s栈出栈
s.push(T);
op栈出栈
}
while(op栈顶元素不是'#') //把树结点的关系连起来
{
T=new BiTNode;
op栈顶元素赋值给T->data
op栈出栈
T->rchild=s.top();
s栈出栈
T->lchild=s.top();
s栈出栈
s.push(T);
}
double EvaluateExTree(BTree T)计算表达式树
定义a,b
if 树T不空
if 左右孩子都为空
return T->data-'0';
a=EvaluateExTree(T->lchild)
b=EvaluateExTree(T->rchild)
判断T->data
如果是'+'
return a+b
如果是'-'
rerurn a-b
如果是'*'
return a*b
如果是'/'
if b==0
输出divide 0 error!
退出程序
否则
return a/b
2.1.2代码截图(注意,截图,截图,截图。不要粘贴博客上。)###
2.1.3本题PTA提交列表说明。###
Q1:把表达式建成树比较有难度
A1:叶子结点都是表达式中的数字,首先遇到数字就赋值给树结点,然后把结点进s栈。遇到运算符就比较复杂了,先要判断运算符和op栈顶元素的大小。若该运算符大于op栈顶元素,就要先把op栈顶元素和s栈里元素关系先建起了。小于则把运算符进op栈。等于则栈顶元素出栈。最后再把栈s、op的关系建起来,op里面的元素为根结点,s栈里面的元素为根的左右孩子。再把新建成的分支进s栈,重复操作,直到op栈顶元素不是'#'。
2.2 题目2:7-4 jmu-ds-二叉树叶子结点带权路径长度和##
2.2.1设计思路(伪代码)###
定义树的结构体
主函数做建树函数的调用和计算带权路径长度和
BinTree CreateBtree(string str,int i)
定义BinTree树BT
if i>str.size()-1
return NULL;
if str[i]=='#'
return NULL;
生成新结点BT
BT->Data=str[i];
BT->Left=CreateBtree(str,2*i);
BT->Right=CreateBtree(str,2*i+1);
return BT;
void GetWpl(BinTree BT,int &wpl,int h)
if BT==NULL
return ;
else
if BT的左右孩子都为空
wpl+=h*(BT->Data-48); //字符转数字(减去'0'=48)
h开始重新记录置为0
h++;
GetWpl(BT->Left,wpl,h);
GetWpl(BT->Right,wpl,h);
2.2.2代码截图(注意,截图,截图,截图。不要粘贴博客上。)###
2.2.3本题PTA提交列表说明。###
Q1:刚开始在编译器上运行的结果不是题目中的72
A1:计算wpl时,直接这么写wpl+=h*BT->Data,忘记BT->Data是字符,不是数字,所以计算出来的当然不是72。应该改成wpl+=h*(BT->Data-48),要再减去字符'0'即可,还有就是计算wpl后,h要置为0,用于其他叶子结点计算wpl。
2.3 题目3:7-5 jmu-ds-输出二叉树每层节点##
2.3.1设计思路(伪代码)###
先按题目递归法建树
void LevelOrder(BinTree BT) //层次遍历
定义BinTree型队列qt;
定义int型level,flag;
定义BinTree型curNode,lastNode;
curNode=lastNode=BT;
if BT==NULL
输出NULL
return ;
else
BT进队
while(!qt.empty())
{
if curNode==lastNode
{
level++;
用flag来控制输出level:前是否要换行
lastNode=qt.back();
}
curNode=qt.front();
输出curNode->Data
if curNode->Left非空
curNode->Left进队
if curNode->Right非空
curNode->Right进队
出队
}
2.3.2代码截图(注意,截图,截图,截图。不要粘贴博客上。)###
2.3.3本题PTA提交列表说明。###
Q1:怎么知道每层结点有哪几个
A1:将根结点进栈,先将curNode,lastNode都置为BT。只有当curNode,lastNode相等时,即curNode到达每层最后一个元素,再输出层次。用curNode记录队头,把队头的左右孩子进队,用lastNode记录队尾。重复操作,直到队列为空。
3、阅读代码#
3.1 题目##
二叉树剪枝
给定二叉树根结点 root ,此外树的每个结点的值要么是 0,要么是 1。返回移除了所有不包含 1 的子树的原二叉树。
3.2 解题思路##
该题采用后序遍历的方法,若树为空,则返回null。接着递归左子树和右子树。若有结点左、右孩子都为空,且该结点的值为0,则返回努力了,否则返回root
3.3 代码截图##
3.4 学习体会##
这题虽然做法是递归,但先序遍历和后序遍历有差别,采用先序遍历则行不通。因为前序只能删除叶子结点为0的,但非叶子为0并且左右结点为0的情况却不行。而采用后序遍历,效果就不同了,后序遍历从叶子结点开始判断删除,若有上述情况,则那个结点也能成为叶子结点,从而被删掉。
所以我们要全面看待问题,不同顺序遍历效果可能是不同的,这种遍历顺序行不通,其他种遍历顺序也许就别有洞天,这道题就是一个很好的案例。