二叉树类型题合集(左神算法初级班C++实现)

58 篇文章 1 订阅

二叉树类型题合集

是否为搜索二叉树

事实上如果一个二叉树中序遍历的结果是升序的,它就是一颗搜索二叉树,所以,我们可以在中序遍历的基础上改

先来定义节点

struct Node {
    int value;
    Node *left;
    Node *right;

    Node() : value(0), left(nullptr), right(nullptr) {}

    

    Node(int x, Node *left, Node *right) : value(x), left(left), right(right) {}
};

这个节点的定义方法我参考了leetcode

然后我们看如何利用结点,搭建起一棵二叉树

Node* bT(){
    Node * head = new Node(8);
    head->left = new Node(6);
    head->right = new Node(10);
    head->left->left = new Node(4);
    head->left->right = new Node(7);
    head->left->left->left = new Node(1);
    head->left->left->right = new Node(5);
    head->right->left = new Node(9);
    head->right->right = new Node(11);
    return head;
}

上面的代码搭建了如下一颗二叉树,然后返回它的头节点地址

在这里插入图片描述

然后是递归版本和非递归版本的中序遍历

//递归版中序遍历
void inOrderRecur(Node *head){
    if(!head){
        return;
    }
    inOrderRecur(head->left);
    cout<<head->value<<" ";
    inOrderRecur(head->right);
}

//非递归版中序遍历
void inOrderUnRecur(Node* head){
    cout<<endl;
    if(head){
        auto *sta = new stack<Node*>() ;
        while(!sta->empty()||head){
            if(head){
                sta->push(head);
                head = head->left;
            }else{
                head = sta->top();
                sta->pop();
                cout<<head->value<<" ";
                head = head->right;
            }
        }
    }
    cout<<endl;
}

然后可以写代码测试一下结果

void test(){
    inOrderRecur(bT());
    inOrderUnRecur(bT());
}

int main(){
    test();
    return 0;
}

输出结果如下

1 4 5 6 7 8 9 10 11
1 4 5 6 7 8 9 10 11

这样我们可以明显的看出上面的二叉树是一颗搜索二叉树

然后对中序遍历的代码稍作更改

//递归版本
int preValue = -10000;
bool isBST(Node *head){
    if(!head){
         return true;
    }
    bool isLeftBst = isBST(head->left);
    if(!isLeftBst)//判断左数是不是搜索二叉树,不是的话返回false
        return false;
    if(head->value<=preValue)//看看当前节点是否比前一个节点小,如果小,返回false
        return false;
    else
        preValue  = head->value;//如果大,那当前值设置为preValue;
    //右树如果是搜索二叉树,那么整棵树是搜索二叉树,如果不是那么整棵树都不是
    return isBST(head->right);
}
//非递归版本
bool isBSTUnRecur(Node* head){

    if(head){
        int preValue = -10000;
        auto *sta = new stack<Node*>() ;
        while(!sta->empty()||head){
            if(head){
                sta->push(head);
                head = head->left;
            }else{
                head = sta->top();
                sta->pop();
                if(head->value<=preValue)
                    return false;
                else
                    preValue = head->value;
                head = head->right;
            }
        }
    }
    return true;
}

2、判断是否完全二叉树

这道题主要用的方法是BFS,即宽度优先遍历

判断条件如下:

(1)任何一个节点,有右孩子而无左孩子,返回false

(2)遇到一个有左无右的节点后,必须保证后面的所有节点都是叶节点,否则不是完全二叉树

bool isCBT(Node*head){
    if(head == nullptr){
        return true;
    }
    auto *que = new queue<Node*>();
    //是否遇到过左右两个孩子不双全的节点
    bool leaf = false;
    Node *l = nullptr;
    Node *r = nullptr;
    que->push(head);
    while(!que->empty()){
        head = que->front();
        que->pop();
        l = head->left;
        r = head->right;
        if( (leaf&&(l||r))//条件二
        ||(!l&&r)){//条件一
            return false;
        }
        if(l) que->push(l);
        if(r) que->push(r);
        if(!l||!r) leaf = true;//左右孩子不双全
    }
    return true;
}

3、判断是否是满二叉树

先求二叉树的最大深度,再求二叉树的节点个数N,二者满足如下关系则说明是满二叉树,代码在下一个问题解决之后再展示
N = 2 l − 1 N = 2^l -1 N=2l1

4、判断是否平衡二叉树(二叉树题目套路)

平衡二叉树是指:对与任何一棵子树,左子树和右子树的高度差都不能超过1

struct ReturnType{
    bool isBalanced;
    int height;
    ReturnType(bool isB, int hei):isBalanced(isB),height(hei){}
};

ReturnType* process(Node* x){
    
    //base case
    if(!x) return new ReturnType(true, 0);

    ReturnType leftData = *process(x->left);
    ReturnType rightData = *process(x->right);

    int height = max(leftData.height, rightData.height)+1;

    bool isBalanced = leftData.isBalanced&&rightData.isBalanced
            &&abs(leftData.height-rightData.height)<2;
    ReturnType *ans = new ReturnType(isBalanced, height);

    return ans;

}
bool isBalanced(Node * head){
    return process(head)->isBalanced;
}

用上面的套路也可以写搜索二叉树的判断

判断条件如下:

(1)左子树是否搜索二叉树

(2)右子树是否搜索二叉树

(3)左边的最大值是否小于右树的最小值

所以我们需要的返回值类型,

如下:(1)是否是搜索二叉树

​ (2)整棵树的最小值

​ (3)整棵树的最大值

struct ReturnData{
    bool isBST;
    int min;
    int max;
    ReturnData(bool is, int mi, int ma):isBST(is), min(mi), max(ma){}
};

ReturnData * process1(Node *x){
    if(!x){
        return nullptr;
    }
    ReturnData* leftData = process1(x->left);
    ReturnData* rightData = process1(x->right);

    int Min = x->value;
    int Max = x->value;
    if(leftData){
        Min = min(Min, leftData->min);
        Max = max(Max, leftData->max);
    }
    if(rightData){
        Min = min(Min, leftData->min);
        Max = max(Max, leftData->max);
    }

//    bool isBST = true;
//    if(leftData&&(!leftData->isBST || leftData->max>=x->value))
//        isBST = false;
//    if(rightData&&(!rightData->isBST || rightData->min<=x->value))
//        isBST = false;

    bool isBST = false;
    if(
            (leftData?(leftData->isBST&&leftData->max<x->value): true)
            &&(rightData?(leftData->isBST&&leftData->max<x->value):true)
            ){
        isBST = true;
    }

    return new ReturnData(isBST, Min, Max);
}

bool isBST1(Node * x){
    return process1(x)->isBST;
}

上面的这种套路,据左神说,可以解决一切树形DP的问题,

这个套路有两个方面,第一个方面是你怎么想这个问题:第一就是可以从左右两边来获取信息

第二个方面是,怎么写代码,代码结构是什么都一目了然

按照这个套路,我们开始解决满二叉树的问题

struct Info{
    int height;
    int nodes;
    Info(int h, int n){
        height = h;
        nodes = n;
    }

};

Info* processInfo(Node *x){
    if(!x) return new Info(0, 0);
    Info * leftData = processInfo(x->left);
    Info * rightData = processInfo(x->right);
    int height = max(leftData->height, rightData->height)+1;
    int nodes = leftData->nodes + rightData->nodes + 1;
    return new Info(height, nodes);
}

bool isF(Node *head){
    if(!head) return true;
    Info *data = processInfo(head);
    return data->nodes == (1<<data->height-1);//相当于2^l-1

}

下面放一下刚才的所有代码

#include <iostream>
#include<stack>
#include<queue>
#include<cmath>
using namespace std;
struct Node {
    int value;
    Node *left;
    Node *right;

    Node() : value(0), left(nullptr), right(nullptr) {}

    Node(int x) : value(x), left(nullptr), right(nullptr) {}

    Node(int x, Node *left, Node *right) : value(x), left(left), right(right) {}
};
//------------------------是否是搜索二叉树----------------------

//递归版中序遍历
void inOrderRecur(Node *head){
    if(!head){
        return;
    }
    inOrderRecur(head->left);
    cout<<head->value<<" ";
    inOrderRecur(head->right);
}
//递归版本判断搜索二叉树
int preValue = -10000;
bool isBST(Node *head){
    if(!head){
         return true;
    }
    bool isLeftBst = isBST(head->left);
    if(!isLeftBst)//判断左数是不是搜索二叉树,不是的话返回false
        return false;
    if(head->value<=preValue)//看看当前节点是否比前一个节点小,如果小,返回false
        return false;
    else
        preValue  = head->value;//如果大,那当前值设置为preValue;
    //右树如果是搜索二叉树,那么整棵树是搜索二叉树,如果不是那么整棵树都不是
    return isBST(head->right);
}
//非递归版中序遍历
void inOrderUnRecur(Node* head){
    cout<<endl;
    if(head){
        auto *sta = new stack<Node*>() ;
        while(!sta->empty()||head){
            if(head){
                sta->push(head);
                head = head->left;
            }else{
                head = sta->top();
                sta->pop();
                cout<<head->value<<" ";
                head = head->right;
            }
        }
    }
    cout<<endl;
}
//非递归版本
bool isBSTUnRecur(Node* head){

    if(head){
        int preValue = -10000;
        auto *sta = new stack<Node*>() ;
        while(!sta->empty()||head){
            if(head){
                sta->push(head);
                head = head->left;
            }else{
                head = sta->top();
                sta->pop();
                if(head->value<=preValue)
                    return false;
                else
                    preValue = head->value;
                head = head->right;
            }
        }
    }
    return true;
}
//--------------是否是完全二叉树------------------------
bool isCBT(Node*head){
    if(head == nullptr){
        return true;
    }
    auto *que = new queue<Node*>();
    //是否遇到过左右两个孩子不双全的节点
    bool leaf = false;
    Node *l = nullptr;
    Node *r = nullptr;
    que->push(head);
    while(!que->empty()){
        head = que->front();
        que->pop();
        l = head->left;
        r = head->right;
        if( (leaf&&(l||r))//条件二
        ||(!l&&r)){//条件一
            return false;
        }
        if(l) que->push(l);
        if(r) que->push(r);
        if(!l||!r) leaf = true;
    }
    return true;
}

//--------------------是否是平衡二叉树-----------------------
struct ReturnType{
    bool isBalanced;
    int height;
    ReturnType(bool isB, int hei):isBalanced(isB),height(hei){}

};

ReturnType* process(Node* x){
    //base case
    if(!x) return new ReturnType(true, 0);

    ReturnType leftData = *process(x->left);
    ReturnType rightData = *process(x->right);

    int height = max(leftData.height, rightData.height)+1;

    bool isBalanced = leftData.isBalanced&&rightData.isBalanced
            &&abs(leftData.height-rightData.height)<2;
    ReturnType *ans = new ReturnType(isBalanced, height);

    return ans;

}
bool isBalanced(Node * head){
    return process(head)->isBalanced;
}


//---------------------是否搜索二叉树套路版---------------

struct ReturnData{
    bool isBST;
    int min;
    int max;
    ReturnData(bool is, int mi, int ma):isBST(is), min(mi), max(ma){}
};

ReturnData * process1(Node *x){
    if(!x){
        return nullptr;
    }
    ReturnData* leftData = process1(x->left);
    ReturnData* rightData = process1(x->right);

    int Min = x->value;
    int Max = x->value;
    if(leftData){
        Min = min(Min, leftData->min);
        Max = max(Max, leftData->max);
    }
    if(rightData){
        Min = min(Min, leftData->min);
        Max = max(Max, leftData->max);
    }

//    bool isBST = true;
//    if(leftData&&(!leftData->isBST || leftData->max>=x->value))
//        isBST = false;
//    if(rightData&&(!rightData->isBST || rightData->min<=x->value))
//        isBST = false;

    bool isBST = false;
    if(
            (leftData?(leftData->isBST&&leftData->max<x->value): true)
            &&(rightData?(leftData->isBST&&leftData->max<x->value):true)
            ){
        isBST = true;
    }

    return new ReturnData(isBST, Min, Max);
}

bool isBST1(Node * x){
    return process1(x)->isBST;
}

//---------------------是否为满二叉树----------------------
struct Info{
    int height;
    int nodes;
    Info(int h, int n){
        height = h;
        nodes = n;
    }

};

Info* processInfo(Node *x){
    if(!x) return new Info(0, 0);
    Info * leftData = processInfo(x->left);
    Info * rightData = processInfo(x->right);
    int height = max(leftData->height, rightData->height)+1;
    int nodes = leftData->nodes + rightData->nodes + 1;
    return new Info(height, nodes);
}

bool isF(Node *head){
    if(!head) return true;
    Info *data = processInfo(head);
    return data->nodes == (1<<data->height-1);//相当于2^l-1

}

Node* bT(){
    Node * head = new Node(8);
    head->left = new Node(6);
    head->right = new Node(10);
    head->left->left = new Node(4);
    head->left->right = new Node(7);
    head->left->left->left = new Node(1);
    head->left->left->right = new Node(5);
    head->right->left = new Node(9);
    head->right->right = new Node(11);
    return head;
}

void test(){
//    inOrderRecur(bT());//                          1
//    inOrderUnRecur(bT());//                        1
//    cout<<isBST(bT())<<endl;//                     1
//    cout<<isBSTUnRecur(bT())<<endl;//              1
//    cout<<isCBT(bT())<<endl;//                     1
//    cout<<isBalanced(bT())<<endl;//                1
//    cout<<isBST1(bT())<<endl;//                    1
//    cout<<isF(bT())<<endl;//                       0

}

int main(){
    test();
    return 0;
}

最低公共祖先:

#include<iostream>
#include<map>
#include<set>

using namespace std;
using namespace __gnu_cxx;

struct Node {
    int value;
    Node *left;
    Node *right;

    Node(int x) : value(x), left(nullptr), right(nullptr) {}
};

void process(Node *head, map<Node *, Node *> *fatherMap) {
    if (!head) return;
    fatherMap->insert(make_pair(head->left, head));
    fatherMap->insert(make_pair(head->right, head));
    process(head->left, fatherMap);
    process(head->right, fatherMap);
}

Node *lca(Node *head, Node *o1, Node *o2) {
    auto *fatherMap = new map<Node *, Node *>();
    fatherMap->insert(make_pair(head, head));
    process(head, fatherMap);
    auto *set1 = new set<Node *>();
    set1->insert(o1);
    Node *cur = o1;
    while (cur != fatherMap->find(cur)->second) {
        set1->insert(cur);
        cur = fatherMap->find(cur)->second;
    }
    set1->insert(head);
    cur = o2;
    while (cur != fatherMap->find(cur)->second) {
        if (set1->find(cur) != set1->end())
            return cur;
        else {
            cur = fatherMap->find(cur)->second;
        }
    }
    return head;
}


int main() {
    Node *head = new Node(8);
    head->left = new Node(6);
    head->right = new Node(10);
    head->left->left = new Node(4);
    Node *o1 = head->left->right = new Node(7);
    Node *o2 = head->left->left->left = new Node(1);
    head->left->left->right = new Node(5);
    head->right->left = new Node(9);
    head->right->right = new Node(11);
    cout<<lca(head, o1, o2)->value<<endl;
}

输出:6

左神原版本的代码用的是hash_ map,但是由与C++hash_map, 不支持自定义数据类型(虽然可以自定义hash模板),所以我只能用map了

在二叉树中找到一个节点的后继节点

后继节点,是中序遍历一个节点的的下一个节点

还是最开始的二叉树,它中序遍历的结果是1,4,5,6,7,8,9,10,11

那么节点4的后继节点就是5

在这里插入图片描述

二叉树的序列化和反序列化

在这里插入图片描述

微软面试题,折纸条

在这里插入图片描述

所以要从上到下打印所有折痕的方向,就是这颗二叉树中序遍历

这颗树的特点是,头节点是凹折痕,每个左子树的头节点都是凹折痕,每个右子树头节点都是凸折痕

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值