第五章 树和二叉树
本章我们重点学习了树和二叉树的定义、二叉树的性质、存储结构、二叉树的先中后序遍历。简略的学习了树和森林的存储结构、遍历,大致讲解了哈夫曼树的基本感念。在学习过程中,建树和二叉树的遍历对我来讲比较难。建树可以用顺序存储也可以用二叉链表存储,二叉树的遍历可以用递归实现也可以用非递归实现。下面主要讲讲我在PTA做题过程的一些感想和思路。
List Leaves
这道题的思路很简单: 构造二叉树的结点结构体、建立二叉树、利用队列输出叶子结点
第一步 构造二叉树的结点结构体
由于这道题的数据N只在10以内,所以我用了顺序存储结构。
1 typedef struct{ //定义二叉树的结点结构 2 int Left; 3 int Right; 4 }BiTreenode;
第二步 建立二叉树
这里要注意的问题有:
1.输入的是char类型数据,因此为了标号方便要将其ASCII码减去0的ASCII码
2. 要定义一个数组root(bool类型或者int类型),以利于标记这个结点的子树是否是根结点
int Buildtree(BiTreenode T[]){ bool root[10]={false}; int n,i; char x,y; cin>>n; for(i=0;i<n;i++){ cin>>x>>y; if(x!=‘-‘){//判断左儿子是否为空,若不为空则左二子不为根结点,赋值为true T[i].Left=x-‘0‘; root[T[i].Left]=true; } else T[i].Left=-1; if(y!=‘-‘){ //判断右儿子是否为空,若不为空则右儿子不为根结点,赋值为true T[i].Right=y-‘0‘; root[T[i].Right]=true; } else T[i].Right=-1; } for (int i=0; i<n; i++){//寻找根结点 ,当 root[]为-1时该式子成立,返回i的下标,即根节点的下标 if(!root[i]) return i; } }
第三步 利用队列输出叶子结点
利用队列的好处是先进先出,而且在push一个数据之后就将它pop出来直接对它的左右孩子进行比较,非常方便
void OrderTree(BiTreenode T[],int x){//利用队列输出叶子结点 queue<int> q; int k; q.push(x);//将根节点入队 while(!q.empty()){//当队列不为空的时候,继续执行循环 int tmp=q.front();//访问队列的首结点,也就是将最早入队的结点的下标赋值给tmp if(T[tmp].Left!=-1) //若该节点的左儿子不为空,则将它压入队列中 q.push(T[tmp].Left); if(T[tmp].Right!=-1)//若该节点的右儿子不为空,则将它压入队列中 q.push(T[tmp].Right); q.pop(); //弹出队列中的第一个元素 if(T[tmp].Left==-1 && T[tmp].Right==-1){ //若该结点的左儿子和右儿子均为空,则该结点为叶子结点,输出该叶子结点 cout<<tmp; if(!q.empty()) //若队列不为空,则输出的不是最后一个叶子结点,在输出空格 cout<<" "; } } }
树的同构
这道题的思路主要是:构造结点结构体、构造二叉树、将两棵二叉树进行比较。
第一步 构造结点结构体
这道题我也是用了顺序存储结构,与上一道题不一样的地方是,这道题需要输入字符域element。
typedef struct Treenode{ char element; int left; int right; }Treenode;
第二步 构造二叉树
与上一道题目大同小异,主要是这里需要构造两棵树。
第三步 将两棵二叉树进行比较
这个步骤有些复杂,主要是在比较过程中要把逻辑思路搞清楚。
1. 两棵树都是空树的情况
2. 其中一棵树是空树的情况下
3. 根节点都存在但数值不同
4. 左子树不存在,则递归判断右子树
5. 左子树同时不空则无需交换左右子树,否则交换左右子树
bool Comparetree(int R1,int R2){ if( (R1==Null) && (R2==Null) ) return true;//两棵树都为空,则同构 if( ((R1==Null) && (R2!=Null)) || ((R1!=Null) && (R2==Null)) ) return false;//两棵树中有一棵为空,另外一棵树不为空,则不同构 if( T1[R1].element!=T2[R2].element ) return false;//若两棵树都不为空,但树根的值不相同,则不同构 if( (T1[R1].left==Null) && (T2[R2].left==Null) ) return Comparetree( T1[R1].right,T2[R2].right );//两棵树都不为空,根的值相同。若左子树都为空,则是否同构取决于右边,递归调用右子树的判别 if( ((T1[R1].left!=Null) && (T2[R2].left!=Null)) && ((T1[T1[R1].left].element)==(T2[T2[R2].left].element)) ) return(Comparetree(T1[R1].left,T2[R2].left) && Comparetree(T1[R1].right,T2[R2].right));//左子树是否同时不空,若同时不空则无需交换左右子树 else return (Comparetree(T1[R1].left,T2[R2].right) && Comparetree(T1[R1].right,T2[R2].left)); };
目标总结:
完成了三分之二的题解,比上次进步一点。
下次目标:
完成所有题解。
原文地址:https://www.cnblogs.com/butterboy/p/10810514.html