是否完全二叉搜索树

将一系列给定数字顺序插入一个初始为空的二叉搜索树(定义为左子树键值大,右子树键值小),你需要判断最后的树是否一棵完全二叉树,并且给出其层序遍历的结果。

输入格式:

输入第一行给出一个不超过20的正整数N;第二行给出N个互不相同的正整数,其间以空格分隔。

输出格式:

将输入的N个正整数顺序插入一个初始为空的二叉搜索树。在第一行中输出结果树的层序遍历结果,数字间以1个空格分隔,行的首尾不得有多余空格。第二行输出YES,如果该树是完全二叉树;否则输出NO

输入样例1:

9
38 45 42 24 58 30 67 12 51

输出样例1:

38 45 24 58 42 30 12 67 51
YES

输入样例2:

8
38 24 12 45 58 67 42 51

输出样例2:

38 45 24 58 42 12 67 51
NO

通过双队列层序遍历标记每个结点的深度 

通过递归判断是否搜索树

通过遍历树将每个节点深度存到全局变量数组中 判断第1—n-1层是否全满

通过O(2^(层数-1))的for循环判断最后一层是否会出现一边子树为完美,另一边子树为完全的情况​​​​​​​

#include<bits/stdc++.h>
using namespace std;

typedef struct BinaryTree{
    int data;
    struct BinaryTree* left;
    struct BinaryTree* right;
    int deep;
}*BT;

int tree[20];

void Create(BT &root , int data);//创建二叉搜索树
bool IsBST(BT &root);//判断是否二叉搜索树
bool IsCBT(BT &root);//判断是否完全二叉树
void PrintIn(BT & root);//打印后序遍历
void dfs(BT &root);//搜索每个深度下的节点个数

int arr[5];
int cur = 0;

int main()
{
    int N;
    cin >> N;
    BT root = NULL;
    for(int i = 0; i < N; i++){
        int data;
        cin >> data;
        Create(root , data);
    } 
    PrintIn(root);
    if(IsBST(root) && IsCBT(root)){
        cout << "\nYES";
    }else{
        
        cout << "\nNO";
    }
    return 0;
}


void Create(BT &root , int data){
    if(root == NULL){
        root = (BT)malloc(sizeof(struct BinaryTree));
        root->data = data;
        root->left = NULL;
        root->right = NULL;
    }else{
        if(data > root->data){
            Create(root->left , data);
        }else{
            Create(root->right , data);
        }
    }
}

int deep = 1;

void PrintIn(BT & root){
    queue<BT> father;
    queue<BT> son;
    father.push(root);
    tree[cur] = root->data;
    while(!father.empty()){
        BT p = father.front();
        if(cur == 0){
            cout << p->data;
        }else{
            cout << " " << p->data;
        }
        p->deep = deep;
        father.pop();
        if(p->left){
            son.push(p->left);
            tree[(cur + 1) * 2 - 1] = p->left->data;
        }else{
            tree[(cur + 1) * 2 - 1] = -1;
        }
        if(p->right){
            son.push(p->right);
            tree[(cur + 1) * 2] = p->right->data;
        }else{
            tree[(cur + 1) * 2] = -1;
        }   
        cur ++;
        //每一层处理完后 开始处理下一层
        if(father.empty()){
            queue<BT> tmp = father;
            father = son;
            son = tmp;
            deep ++;
        }
    }
}

bool IsBST(BT &root){
    if(!root->right && root->left){
       if(root->left->deep == deep - 1){
           return IsBST(root->left);
       }else{
           return false;
       }
    }else if(root->left && root->right){
        if(root->left->data < root->right->data){
            return false;
        }else{
            return IsBST(root->left) && IsBST(root->right);
        }
    }else if(!root->left && !root->right){
        return true;
    }else{
        return false;
    }
}

bool IsCBT(BT &root){
    dfs(root);
    for(int i = 0;i < deep - 2;i ++){
        if(arr[i] != (int)pow(2,i)){
            return false;
        }
    }
    int flag1 = 0;
    int flag2 = 0;
    int begin = deep - 3;
    int end = begin + (int)pow(2,deep - 3);
    for(int i = begin;i < end;i ++){
        if(tree[i * 2 + 1] != -1 && tree[i * 2 + 2] != -1 && flag1 == 1){
            flag2 = 1;
            break;
        }else if(tree[i * 2 + 1] != -1 && tree[i * 2 + 2] == -1 && flag1 == 0){
            flag1 = 1;
        }else if(tree[i * 2 + 1] != -1 && tree[i * 2 + 2] == -1 && flag1 == 1){
            flag2 = 1;
            break;
        }else if(tree[i * 2 + 1] == -1 && tree[i * 2 + 2] == -1 && flag1 == 0){
            flag1 = 1;
        }
    }
    if(flag1 == 1 && flag2 == 1){
        return false;
    }
    return true;
}

void dfs(BT &root ){
    if(root){
        arr[root->deep - 1]++;
        dfs(root->left);
        dfs(root->right);
    } 
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

R_1220

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

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

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

打赏作者

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

抵扣说明:

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

余额充值