第五章题解

Posted butterboy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第五章题解相关的知识,希望对你有一定的参考价值。

第五章 树和二叉树

本章我们重点学习了树和二叉树的定义、二叉树的性质、存储结构、二叉树的先中后序遍历。简略的学习了树和森林的存储结构、遍历,大致讲解了哈夫曼树的基本感念。在学习过程中,建树和二叉树的遍历对我来讲比较难。建树可以用顺序存储也可以用二叉链表存储,二叉树的遍历可以用递归实现也可以用非递归实现。下面主要讲讲我在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));
};

目标总结:

完成了三分之二的题解,比上次进步一点。

下次目标:

完成所有题解。

 

以上是关于第五章题解的主要内容,如果未能解决你的问题,请参考以下文章

《区块链编程》第五章

第五章 MyBatis代码生成器和缓存配置

第五章 Python 函数

代码大全2--第五章--Read.2017

“全栈2019”Java第五章:IntelliJ IDEA代码自动提示

第一行代码笔记-第五章