BTS二叉搜索树 1043 Is It a Binary Search Tree (25分)

void Creat(BiNode *&root,int i1,int i2,int len)

Node* &root,这个是指针的引用,

主要目的是为了通过在函数内改Node* root的值(注意区分所指的值的区别),
实参(就是你调用时传入的参数)同步获得改变,也就相当于 “传址”,
否则就是“传值”了,应该明白了吧?

#include<stdio.h>
 
void plus(int p, int *q){
    
    
 
    p++;
    (*q)++;
}
 
main(){
    
    
 
    int a = 1;
    int b = 1;
     
    plus(a, &b); // 把baia的值和b的地址传给plus函数du
     
    printf("a=%d, b=%d\n", a, b); // 经过plus处理,得到结zhi果,a不变,b变;dao
void insert(node* &root,int data){
    
    //node* root=NULL;//定义头结点
    if(root==NULL){
    
    //找到空节点,即为需要插入的位置
        root=new node;
        root->data=data;
        root->left=root->right=NULL;//此句不能漏
        return;
    }
    if(data<root->data)insert(root->left,data);//插在左子树
    else insert(root->right,data);//插在右子树
    
}

//16
//1043 Is It a Binary Search Tree (25分)


//8
//38 24 12 45 58 67 42 51//(定义为左子树键值大,右子树键值小)
//=======================
//38 45 24 58 42 12 67 51//层序遍历的结果
//NO//输出YES,如果该树是完全二叉树;否则输出NO。
//1.用数组存储原始的序列
//2.根据原始的序列--建立二叉树
//3.根据建立的二叉树来获得对应的先序,镜像先序,后序,镜像后序的序列,用数组存储
//4.将先序/先序镜像序列与原始序列进行比较,输出“Yes”或“No”---如果是,输出相应后序/后序镜像数组的元素

#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
vector<int>origin,pre,preM,post,postM;//初始序列


struct node{
    
    
    int data;//数据域
    node *left,*right;//指针域
};




void insert(node* &root,int data){
    
    //node* root=NULL;//定义头结点
    if(root==NULL){
    
    //找到空节点,即为需要插入的位置
        root=new node;
        root->data=data;
        root->left=root->right=NULL;//此句不能漏
        return;
    }
    if(data<root->data)insert(root->left,data);//插在左子树
    else insert(root->right,data);//插在右子树
    
}


void preOrder(node* root,vector<int> &vi){
    
    //先序遍历,结果存在vi
    if(root==NULL)return;
    vi.push_back(root->data);
    preOrder(root->left,vi);
    preOrder(root->right,vi);
    
}
//镜像树先序遍历,结果存在vi
//所谓镜像树---是指交换二叉树所有左右子树而形成的树
//(左子树的所有节点大于或等于根节点)
//(根节点数据域小于右子树所有节点的数据域)//-----二叉排序树
void preOrderMirror(node* root,vector<int>& vi){
    
    
    if(root==NULL)return;
    vi.push_back(root->data);
    preOrderMirror(root->right,vi);
    preOrderMirror(root->left,vi);
}

void postOrder(node* root,vector<int> &vi){
    
    //后序遍历,结果存在vi
    if(root==NULL)return;
    postOrder(root->left,vi);
    postOrder(root->right,vi);
    vi.push_back(root->data);
    
}

//镜像树后序遍历,结果存在vi
void postOrderMirror(node* root,vector<int>  vi){
    
    
    if(root==NULL)return;
    postOrderMirror(root->right,vi);
    postOrderMirror(root->left,vi);
    vi.push_back(root->data);
    
}
int main(){
    
    
    
    int n,data;
    node* root=NULL;//定义头结点
    cin>>n;//输入节点个数
    for(int i=0;i<n;i++){
    
    
        cin>>data;
        origin.push_back(data);//将数据加到origin
        insert(root,data);//将data插入二叉树
    }
    
    
    
    preOrder(root,pre);//求先序--根左右
    preOrderMirror(root,preM);//求镜像树先序--根右左
    postOrder(root,post);///求后序
    postOrderMirror(root,postM);
    
    if(origin==pre){
    
    //初始序列等于先序序列//origin.push_back(data);//将数据加到origin
        cout<<"YES\n";
        for(int i=0;i<post.size();i++){
    
    
            if(i==0)cout<<post[i];
            else cout<<" "<<post[i];
            
        }
    }else if(origin==preM){
    
    //初始序列等于镜像先序序列
        cout<<"YES\n";
        for(int i=0;i<postM.size();i++){
    
    
            if(i==0)cout<<postM[i];
            else cout<<" "<<postM[i];
        }
    }else{
    
    
        cout<<"NO\n";
    }
    return 0;
}

二叉搜索树
1.使用vector数组来存放初始序列、先序序列、镜像树先序序列,可以方便相互之间的比较,若使用数组,则需要循环才能实现
2.定义根节点,要将其设为空节点(一开始没有元素),在新建节点时要注意把左右子节点的地址设为NULL

二叉树的建立(递归实现)

Node* build(Node* root, int val){
    
    
      if(root == NULL){
    
    
           root = new Node();
           root->val = val;
           return root;
      }
      if(val < root->val) root->left = build(root->left, val);
     else if(val > root->val) root->right = build(root->right, val);
     return root;
}
#include <iostream>
#include <cstdio>
using namespace std;
vector<int>origin;//初始序列


struct node{
    
    
    int data;//数据域
    node *left,*right;//指针域
};




void insert(node* &root,int data){
    
    //node* root=NULL;//定义头结点
    if(root==NULL){
    
    //找到空节点,即为需要插入的位置
        root=new node;
        root->data=data;
        root->left=root->right=NULL;//此句不能漏
        return;
    }
    if(data<root->data)insert(root->left,data);//插在左子树
    else insert(root->right,data);//插在右子树
    
}


int main(){
    
    
    
    int n,data;
    node* root=NULL;//定义头结点
    cin>>n;//输入节点个数
    for(int i=0;i<n;i++){
    
    
        cin>>data;
        origin.push_back(data);//将数据加到origin
        insert(root,data);//将data插入二叉树
    }
    return 0;
}

二叉树的先序遍历

class Solution {
    
    
    public List<Integer> preorderTraversal(TreeNode root) {
    
    
        List<Integer> result = new LinkedList<>();
        preorderHelper(root, result);
        return result;
    }

    private void preorderHelper(TreeNode root, List<Integer> result) {
    
    
        if (root == null) return;
        result.add(root.val); // 访问根节点
        preorderHelper(root.left, result); // 递归遍历左子树
        preorderHelper(root.right, result); //递归遍历右子树
    }
}

void preOrder(node* root,vector<int> &vi){
    
    //先序遍历,结果存在vi
    if(root==NULL)return;
    vi.push_back(root->data);
    preOrder(root->left,vi);
    preOrder(root0>right,vi);
    
}

二叉树的后序遍历
无论对于哪种方式,递归的方法总是很容易实现的,也是很符合直觉的。对于后序遍历,就是先访问左子树,再访问右子树,再访问根节点,即 左->右->根:

class Solution {
    
    
    public List<Integer> postorderTraversal(TreeNode root) {
    
    
        List<Integer> result = new LinkedList<>();
        postorderHelper(root, result);
        return result;
    }

    private void postorderHelper(TreeNode root, List<Integer> result) {
    
    
        if (root == null) return;
        postorderHelper(root.left, result); // 遍历左子树
        postorderHelper(root.right, result); // 遍历右子树
        result.add(root.val); // 访问根节点
    }


}

void postOrder(node* root,vector<int>& vi){
    
    //后序遍历,结果存在vi
    if(root==NULL)return;
    postOrder(root->left,vi);
    postOrder(root->right,vi);
    vi.push_back(root->data);
    
}
int main(){
    
    
    
    int n,data;
    node* root=NULL;//定义头结点
    cin>>n;//输入节点个数
    for(int i=0;i<n;i++){
    
    
        cin>>data;
        origin.push_back(data);//将数据加到origin
        insert(root,data);//将data插入二叉树
    }
    
    
    
    preOrder(root,pre);//求先序--根左右
    preOrderMirror(root,preM);//求镜像树先序--根右左
    postOrder(root,post);///求后序
    
    return 0;
}

与前序遍历和后序遍历相比,代码结构完全一致,差别仅仅是递归函数的调用顺序。

https://blog.csdn.net/weixin_44586473/article/details/90263261?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param#211__18

https://www.pianshen.com/article/7106254596/

完全二叉树

扫描二维码关注公众号,回复: 11919341 查看本文章

首先建立二叉搜索树,
其次需要层序遍历,
重点在于如何判断是完全二叉树,我们分成两种情况,
假设是一个n层的完全二叉树,那么2**(n-1) - 1等于前n - 1层的数目,通过这个,我们可以先判断出前n - 1层是否正确,对于最后一层,如果出现有节点有右子树,但是没有左子树,或者某个结点的左边的表兄弟节点没有左子树或右子树,但是自己却有子孩子,那也不是完全树.

在我写的代码里,emmm,我建立的二叉搜索树仍然是左孩子小于右孩子,这与题目不同,不过在进行层序遍历时,是先将右孩子加入队列,再加入左孩子,所以实质上还是一样的.所以在判断完全二叉搜索树时,所有的左都换成了右,所有的右都换成了左.


分析:
首先二叉搜索树,
我们根据定义建立就好,
但是如何判定其是不是完全二叉树呢?
首先我们要先区别一下满二叉树和完全二叉树的区别。

满二叉树: 假设这个二叉树有n层,那么每一层的节点数都达到最大的二叉树。

完全二叉树:把最后一层去掉就是满二叉树,
同时最后一层:
我们假设最后一层里面如果是满的话是有n个节点,
我们从左往右标号1-n,那么最后一层如果想要有节点的话,
一定要按照标号顺序建立,不能隔过一个或多个标号去建立其他的节点。


完全二叉树
在这里插入图片描述

所以 我们分析一下 完全二叉树的特点:
我们按照层次顺序遍历这颗树的过程中,对于任意一节点x
1 》如果x 有右子树,但是却没有左子树,这肯定不是完全二叉树
2 》如果x 有左子树,但是却没有右子树,那么剩余的所有节点一定要为叶子节点
3 》如果 x 左右子树都没有,那么剩余的所有节点也要为叶子节点

猜你喜欢

转载自blog.csdn.net/weixin_44769957/article/details/108919164