二叉树专题的复习

目录

目录

确定写递归的步骤

1:二叉树的前序后序中序递归遍历

2:求二叉树的最大深度:

3:求二叉树的最小深度

7074:

7075:

 7076:

7077:

7078

7079

7080

书的课后习题 :

p147.(1)  求二叉树的叶子

P148(2):求二叉树是否相同

P148(3):交换二叉树的左右节点:

P148(4):二叉树双序遍历算法:

P148(5)计算二叉树的最大宽度:

P148(6)统计树中度为一的节点数目:

P148(7):输出树中一条路径最长的长度,并输出路径上各个节点的值:

P147(8)输出二叉树中每个叶子结点到根节点的路径:

平时作业:在二叉链表表示的二叉树中查找值为X的结点并输出他的所有祖先非 



确定写递归的步骤

  1. 确定递归函数的参数和返回值: 确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。

  2. 确定终止条件: 写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。

  3. 确定单层递归的逻辑: 确定每一层递归需要处理的信息。在这里也就会重复调用自己来实现递归的过程。

举个例子

1:二叉树的前序后序中序递归遍历

//前序遍历:
class Solution {
public:
    void inorder(TreeNode* root, vector<int>& res) {
        if (!root) {
            return;//函数的终止条件当结点为空终止
        }
        res.push_back(root->val);//单层遍利条件中
        inorder(root->left, res);//左
        inorder(root->right, res);//右
    }
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        inorder(root, res);
        return res;
    }
};
//中序遍历:
class Solution {
public:
    void inorder(TreeNode* root, vector<int>& res) {
        if (!root) {
            return;//函数的终止条件当结点为空终止
        }
        inorder(root->left, res);
        res.push_back(root->val);
        inorder(root->right, res);
    }
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        inorder(root, res);
        return res;
    }
};
//后序遍历:
class Solution {
public:
    void inorder(TreeNode* root, vector<int>& res) {
        if (!root) {
            return;//函数的终止条件当结点为空终止
        }
        inorder(root->left, res);
        inorder(root->right, res);
        res.push_back(root->val);
    }
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        inorder(root, res);
        return res;
    }
};

2:求二叉树的最大深度:

class solution {
public:
    int getdepth(treenode* node) {
        if (node == null) return 0;//确定终止条件
        int leftdepth = getdepth(node->left);       // 左//确定单层逻辑
        int rightdepth = getdepth(node->right);     // 右
        int depth = 1 + max(leftdepth, rightdepth); // 中
        return depth;
    }
    int maxdepth(treenode* root) {
        return getdepth(root);
    }
};

3:求二叉树的最小深度

class Solution {
public:
    int getdepth(TreeNode *node)
    {
        if(node==NULL)
        {
            return 0;
        }
        int leftdepth=getdepth(node->left);
        int rightdepth=getdepth(node->right);
        if(node->left==NULL&&node->right!=NULL)
        {
            return 1+rightdepth;
        }
         if(node->left!=NULL&&node->right==NULL)
        {
            return 1+leftdepth;
        }
        int depth=1+min(leftdepth,rightdepth);
        return depth;

    }
    int minDepth(TreeNode* root) {
        return getdepth(root);
        

    }
};

理解的不是很深刻,以后接着再更 

更新学校的实验为了阶段考试

7074:

我们学校的题都是给个先序遍历的字符串来创建树;

//瑞格上的题一般都是字符串输入一段二叉树的先序序列
#include<iostream>
using namespace std;
#include<algorithm>
typedef struct  BiTNode{
    char data;
    struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
//二叉树的结构
BiTree Creat_Tree()
{
    char ch;
    cin>>ch;
    if(ch=='@'){
        return NULL ;//递归判断条件
    }
    BiTree T;
    T=new BiTNode;//单层递归执行的操作
    T->data=ch;
    T->lchild=Creat_Tree();
    T->rchild=Creat_Tree();//先序遍历法先给节点赋值再给他的左节点赋值再给他的有节点赋值
    return T;
}
int Depth_Tree(BiTree T)
{
    if(!T){
        return 0;//递归终止条件
    }
    int left_depth=Depth_Tree(T->lchild);//单层递归的操作
    int right_depth=Depth_Tree(T->rchild);
    return max(left_depth,right_depth)+1;

}
int main()
{
    BiTree T;
    int DEpth;
    T=Creat_Tree();
    cout<<Depth_Tree(T)<<endl;
   // preorder(T);
}

7075:

二叉树后续遍历没啥好说啊,就变下后序中序和先序就变下顺序就行了

//瑞格上的题一般都是字符串输入一段二叉树的先序序列
#include<iostream>
using namespace std;
#include<algorithm>
typedef struct  BiTNode{
    char data;
    struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
//二叉树的结构
BiTree Creat_Tree()
{
    char ch;
    cin>>ch;
    if(ch=='@'){
        return NULL ;//递归判断条件
    }
    BiTree T;
    T=new BiTNode;//单层递归执行的操作
    T->data=ch;
    T->lchild=Creat_Tree();
    T->rchild=Creat_Tree();//先序遍历法先给节点赋值再给他的左节点赋值再给他的有节点赋值
    return T;
}
void order(BiTree T)
{
    if(!T){
        return ;//递归终止条件
    }
    order(T->lchild);
    order(T->rchild);//单层递归语句
    cout<<T->data;
}
int main()
{
    BiTree T;
    int DEpth;
    T=Creat_Tree();
    order(T);
}

 7076:

找二叉树的叶子比较常见的一种题型了

//瑞格上的题一般都是字符串输入一段二叉树的先序序列
#include<iostream>
using namespace std;
#include<algorithm>
typedef struct  BiTNode{
    char data;
    struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
//二叉树的结构
BiTree Creat_Tree()
{
    char ch;
    cin>>ch;
    if(ch=='@'){
        return NULL ;//递归判断条件
    }
    BiTree T;
    T=new BiTNode;//单层递归执行的操作
    T->data=ch;
    T->lchild=Creat_Tree();
    T->rchild=Creat_Tree();//先序遍历法先给节点赋值再给他的左节点赋值再给他的有节点赋值
    return T;
}
int count_leafs(BiTree T)
{
    if(!T){
        return 0;//递归终止条件
    }
    if(!T->lchild&&!T->rchild){
        return 1;//递归终止条件
    }
    int left_leafs=count_leafs(T->lchild);//单层递归语句找左子树的叶子
    int right_leafs=count_leafs(T->rchild);//再找右子树的叶子
    return left_leafs+right_leafs;
}
int main()
{
    BiTree T;
    int DEpth;
    T=Creat_Tree();
    cout<<count_leafs(T);
}

7077:

借助大神写的讲解明白了点感谢大神   代码随想录

层序遍历借助的是BFS      广度优先遍历

 借助STL中的队列来实现的:

//瑞格上的题一般都是字符串输入一段二叉树的先序序列
#include<iostream>
using namespace std;
#include<algorithm>
#include<queue>
typedef struct  BiTNode{
    char data;
    struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
//二叉树的结构
BiTree Creat_Tree()
{
    char ch;
    cin>>ch;
    if(ch=='@'){
        return NULL ;//递归判断条件
    }
    BiTree T;
    T=new BiTNode;//单层递归执行的操作
    T->data=ch;
    T->lchild=Creat_Tree();
    T->rchild=Creat_Tree();//先序遍历法先给节点赋值再给他的左节点赋值再给他的有节点赋值
    return T;
}
void BFStree(BiTree T)//层序遍历可以看作是广度遍历算法
{
    queue<BiTree>Q;//定义一个树指针的队列 
    if(T){
    Q.push(T);//首先压进去树根
    }
    while(!Q.empty()){
        BiTree R;
        R=Q.front();
        cout<<R->data;
        Q.pop();//弹出队头;
        if(R->lchild){
            Q.push(R->lchild);
        }
        if(R->rchild){
            Q.push(R->rchild);
        }
    }
}
int main()
{
    BiTree T;
    int DEpth;
    T=Creat_Tree();
    BFStree(T);
}

7078

中序遍历没啥好说的了

#include<iostream>
using namespace std;
#include<algorithm>
#include<queue>
typedef struct  BiTNode{
    char data;
    struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
//二叉树的结构
BiTree Creat_Tree()
{
    char ch;
    cin>>ch;
    if(ch=='@'){
        return NULL ;//递归判断条件
    }
    BiTree T;
    T=new BiTNode;//单层递归执行的操作
    T->data=ch;
    T->lchild=Creat_Tree();
    T->rchild=Creat_Tree();//先序遍历法先给节点赋值再给他的左节点赋值再给他的有节点赋值
    return T;
}
void Inorder(BiTree T)
{
    if(!T){
        return ;//递归终止条件
    }
    Inorder(T->lchild);
    cout<<T->data;
    Inorder(T->rchild);//单层递归语句
}
int main()
{
    BiTree T;
    int DEpth;
    T=Creat_Tree();
     // BFStree(T);
    Inorder(T);
}

7079

不写了和7078一摸一样

7080

#include<iostream>
using namespace std;
#include<algorithm>
#include<queue>
typedef struct  BiTNode{
    char data;
    struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
//二叉树的结构
BiTree Creat_Tree()
{
    char ch;
    cin>>ch;
    if(ch=='@'){
        return NULL ;//递归判断条件
    }
    BiTree T;
    T=new BiTNode;//单层递归执行的操作
    T->data=ch;
    T->lchild=Creat_Tree();
    T->rchild=Creat_Tree();//先序遍历法先给节点赋值再给他的左节点赋值再给他的有节点赋值
    return T;
}
void count_leaf(BiTree T)//层序遍历可以看作是广度遍历算法
{
    queue<BiTree>Q;//定义一个树指针的队列 
    if(T){
    Q.push(T);//首先压进去树根
    }
    int count=0;
    while(!Q.empty()){
        BiTree R;
        R=Q.front();
        if(!R->lchild){
            count++;
        }
        Q.pop();//弹出队头;
        if(R->lchild){
            Q.push(R->lchild);
        }
        if(R->rchild){
            Q.push(R->rchild);
        }
    }
    cout<<count<<endl;
}
int main()
{
    BiTree T;
    int DEpth;
    T=Creat_Tree();
     // BFStree(T);
    count_leaf(T);
}

 这道题也是可以用递归地

主要的点在于森林的孩子兄弟表示法中森林的左子树是孩子(长子)右子树是兄弟

书的课后习题 :

p147.(1)  求二叉树的叶子

递归算法:

int count_leafs(BiTree T)
{
    if(!T){
        return 0;
    }
    if(!T->lchild&&!T->rchild){
        return 1;
    }
    int left_leafs=count_leafs(T->lchild);
    int right_leafs=count_leafs(T->rchild);
    return left_leafs+right_leafs;
}

P148(2):求二叉树是否相同

有个要注意的地方就是就是T的左节点和F的右节点相同时并且T的右节点和F的左节点相同时

两棵二叉树也是相同的

//瑞格上的题一般都是字符串输入一段二叉树的先序序列
#include<iostream>
using namespace std;
#include<algorithm>
#include<queue>
typedef struct  BiTNode{
    char data;
    struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
//二叉树的结构
BiTree Creat_Tree()
{
    char ch;
    cin>>ch;
    if(ch=='@'){
        return NULL ;//递归判断条件
    }
    BiTree T;
    T=new BiTNode;//单层递归执行的操作
    T->data=ch;
    T->lchild=Creat_Tree();
    T->rchild=Creat_Tree();//先序遍历法先给节点赋值再给他的左节点赋值再给他的有节点赋值
    return T;
}
bool istrue(BiTree T,BiTree F)
{
    if(!T&&!F){
        return true;
    }
    if(!T&&F){
        return false;
    }
    if(T&&!F){
        return false;
    }
    if(T->data!=F->data){
        return false;
    }
    if(T->data==F->data){
        return (istrue(T->lchild,F->lchild)&&istrue(T->rchild,F->rchild)||istrue(T->lchild,F->rchild)&&istrue(T->rchild,F->lchild));
    }
}
int main()
{
    BiTree T,F;
    T=Creat_Tree();
    F=Creat_Tree();
    cout<<istrue(T,F)<<endl;
}

P148(3):交换二叉树的左右节点:

//瑞格上的题一般都是字符串输入一段二叉树的先序序列
#include<iostream>
using namespace std;
#include<algorithm>
#include<queue>
typedef struct  BiTNode{
    char data;
    struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
//二叉树的结构
BiTree Creat_Tree()
{
    char ch;
    cin>>ch;
    if(ch=='@'){
        return NULL ;//递归判断条件
    }
    BiTree T;
    T=new BiTNode;//单层递归执行的操作
    T->data=ch;
    T->lchild=Creat_Tree();
    T->rchild=Creat_Tree();//先序遍历法先给节点赋值再给他的左节点赋值再给他的有节点赋值
    return T;
}
void Swap_Tree(BiTree T)
{
    if(!T){
        return ;//递归终止条件
    }
    BiTree R;
    R=new BiTNode;
    R=T->lchild;
    T->lchild=T->rchild;
    T->rchild=R;    //先序遍历
    Swap_Tree(T->lchild);//单层递归条件
    Swap_Tree(T->rchild);
}
int main()
{
    BiTree T,F;
    T=Creat_Tree();
    preorder(T);
    cout<<endl;
    Swap_Tree(T);
    preorder(T);
}

P148(4):二叉树双序遍历算法:

#include<iostream>
using namespace std;
#include<algorithm>
#include<queue>
typedef struct  BiTNode{
    char data;
    struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
//二叉树的结构
BiTree Creat_Tree()
{
    char ch;
    cin>>ch;
    if(ch=='@'){
        return NULL ;//递归判断条件
    }
    BiTree T;
    T=new BiTNode;//单层递归执行的操作
    T->data=ch;
    T->lchild=Creat_Tree();
    T->rchild=Creat_Tree();//先序遍历法先给节点赋值再给他的左节点赋值再给他的有节点赋值
    return T;
}
void double_order(BiTree T )
{
    if(!T){
        return ;
    }
    cout<<T->data;
    double_order(T->lchild);
    cout<<T->data;
    double_order(T->rchild);

}
int main()
{
    BiTree T,F;
    T=Creat_Tree();
    double_order(T);
}

P148(5)计算二叉树的最大宽度:

#include<iostream>
using namespace std;
#include<algorithm>
#include<queue>
typedef struct  BiTNode{
    char data;
    struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
//二叉树的结构
BiTree Creat_Tree()
{
    char ch;
    cin>>ch;
    if(ch=='@'){
        return NULL ;//递归判断条件
    }
    BiTree T;
    T=new BiTNode;//单层递归执行的操作
    T->data=ch;
    T->lchild=Creat_Tree();
    T->rchild=Creat_Tree();//先序遍历法先给节点赋值再给他的左节点赋值再给他的有节点赋值
    return T;
}
int Width_Tree(BiTree T)
{
    queue<BiTree>Q;
    int max_width=0;
    int width=1;
    BiTree R;
    Q.push(T);
    while(!Q.empty()){
        int i=0;
        while(i<width){
            R=Q.front();
            Q.pop();
            if(R->lchild){
                Q.push(R->lchild);
            }
            if(R->rchild){
                Q.push(R->rchild);
            }
            i++;
        }
        width=Q.size();
        if(max_width<width){
            max_width=width;
        }
    }
    return max_width;
}
int main()
{
    BiTree T,F;
    T=Creat_Tree();
    int max_width;
    max_width=Width_Tree(T);
    cout<<max_width<<endl;
}

P148(6)统计树中度为一的节点数目:

#include<iostream>
using namespace std;
#include<algorithm>
#include<queue>
typedef struct  BiTNode{
    char data;
    struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
//二叉树的结构
BiTree Creat_Tree()
{
    char ch;
    cin>>ch;
    if(ch=='@'){
        return NULL ;//递归判断条件
    }
    BiTree T;
    T=new BiTNode;//单层递归执行的操作
    T->data=ch;
    T->lchild=Creat_Tree();
    T->rchild=Creat_Tree();//先序遍历法先给节点赋值再给他的左节点赋值再给他的有节点赋值
    return T;
}
int Count(BiTree T)
{
    queue<BiTree>Q;//定义一个树指针的队列 
    if(T){
    Q.push(T);//首先压进去树根
    }
    int count1=0;
    while(!Q.empty()){
        BiTree R;
        R=Q.front();
        Q.pop();//弹出队头;
        if(!R->lchild&&R->rchild){
            count1++;
        }
        if(R->lchild&&!R->rchild){
            count1++;
        }
        if(R->lchild){
            Q.push(R->lchild);
        }
        if(R->rchild){
            Q.push(R->rchild);
        }
    }
    return count1;
}
int main()
{
    BiTree T,F;
    T=Creat_Tree();
    cout<<Count(T)<<endl;
}

P148(7):输出树中一条路径最长的长度,并输出路径上各个节点的值:

#include<iostream>
using namespace std;
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<list>
typedef struct  BiTNode{
    char data;
    struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
//二叉树的结构
vector<char>path;
void FindLongest(BiTree T)
{
    path.push_back(T->data);//根节点压入
    if(!T->lchild&&!T->rchild){
        return ;
    }
    if(Depth_Tree(T->lchild)>=Depth_Tree(T->rchild)){
        FindLongest(T->lchild);
    }
    if(Depth_Tree(T->lchild)<Depth_Tree(T->rchild)){
        FindLongest(T->rchild);
    }
    
}
int main()
{
    BiTree T,F;
    T=Creat_Tree();
    FindLongest(T);
    for(vector<char>:: iterator it=path.begin();it!=path.end();it++)
    {
        cout<<*it<<" ";
    }
    cout<<endl;
    path.clear();

}

P147(8)输出二叉树中每个叶子结点到根节点的路径:

不是很好做先记着努力理解吧:

#include<iostream>
using namespace std;
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<list>
typedef struct  BiTNode{
    char data;
    struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
//二叉树的结构

BiTree Creat_Tree()
{
    char ch;
    cin>>ch;
    if(ch=='@'){
        return NULL ;//递归判断条件
    }
    BiTree T;
    T=new BiTNode;//单层递归执行的操作
    T->data=ch;
    T->lchild=Creat_Tree();
    T->rchild=Creat_Tree();//先序遍历法先给节点赋值再给他的左节点赋值再给他的有节点赋值
    return T;
}
char path[100];
int pathlen=0;//一定要在外面定义全局数组在函数中递归会重复定义的
void AllPath(BiTree T)
{
    int i;
    if(T){
        if(!T->lchild&&!T->rchild){
            for(i=0;i<pathlen;i++){
                cout<<path[i]<<" ";//先数组中的所有值输出
            }
            cout<<T->data;//输出这个叶节点
            cout<<endl;//换行
            return ;//递归终止条件
        }
        else{
            path[pathlen++]=T->data;//如果不是叶节点的话输入数组中
            AllPath(T->lchild);//查找左子树的路径
            AllPath(T->rchild);//查找左子树的路径
        } 
        pathlen--;//出来上面两个递归之后一定是叶子结点且已经加到数组中要把它删去;
        //叶子节点运行完之后删除就会自动到上一个节点的右子树
    }
}
int main()
{
    BiTree T,F;
    T=Creat_Tree();
    AllPath(T);
}

平时作业:在二叉链表表示的二叉树中查找值为X的结点并输出他的所有祖先非 

#include<iostream>
using namespace std;
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<list>
typedef struct  BiTNode{
    char data;
    struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
//二叉树的结构
vector<char>path;
BiTree Creat_Tree()
{
    char ch;
    cin>>ch;
    if(ch=='*'){
        return NULL ;//递归判断条件
    }
    BiTree T;
    T=new BiTNode;//单层递归执行的操作
    T->data=ch;
    T->lchild=Creat_Tree();
    T->rchild=Creat_Tree();//先序遍历法先给节点赋值再给他的左节点赋值再给他的有节点赋值
    return T;
}
bool Search_PostOrder(BiTree T, char x)
{
	if (T != NULL)
	{
        //分别在T的左右子树递归的查找结点值为x的孩子结点
		bool b1 = Search_PostOrder(T->lchild, x);
		bool b2 = Search_PostOrder(T->rchild, x);
		if (T->data == x)//找到了结点值为x的结点,返回true
        {
            //cout<<x<<" ";
			return true;
        }
		if (b1 || b2)//如果结点为x是当前结点的孩子结点
		{
			cout<<T->data<<" ";
			return true;//这里也返回true,向祖先结点表示,值为x的结点在你们的子树里
		}
	}
	return false;//其他情况均返回false
}
int main()
{
    BiTree T,F;
    T=Creat_Tree(); 
    char x;
    cin>>x;
    if(T->data==x){
        cout<<"没有祖先结点";
    }
    else{
        if(!Search_PostOrder(T,x)){
            cout<<x<<"不存在";
        }
        
    }
}

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小李小于

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值