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

    科技2022-07-14  131

    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/

    完全二叉树

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

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


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

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

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


    完全二叉树

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

    Processed: 0.020, SQL: 8