特殊二叉树的建立(二叉搜索树)
首先我们先认识一下二叉搜索树(BST),即任意节点的左节点肯定比该节点小,右节点比该节点大。然后当你中序遍历这棵树的时候,你会惊讶的发现遍历后得到的data是从小到大排序的。
给出如下一颗二叉搜索树:
中序遍历结果就是1 4 5 6 8 9 13
因此对于一个二叉搜索树的建立,只需要判断当前结点的data值和要插入的data值,如果data<root - >data,插入左子树,否则插入右子树
然后按照先序序列的顺序递归插入每个结点就完成了整棵树的建立
附上二叉搜索树的建立代码
#include<iostream>
#include<vector>
#include<cstdio>
using namespace std;
struct node{
int data;
node* l;//指向左孩子
node* r;//右孩子
};
void insert(node* &root,int a)//建树
{
if(root==NULL)//当前位置指向空
{
root=new node;
root->data=a;
root->l=NULL;
root->r=NULL;
}
else
{
if(a>=root->data)insert(root->r,a);
else insert(root->l,a);
}
}
void inorder(node* root)//中序搜索
{
if(root==NULL)return;
preorder(root->l);
cout<<(root->data)<<" ";
preorder(root->r);
}
int main()
{
int n;
cin>>n;
node* rot=NULL;//根结点初始化
for(int i=0;i<n;i++) //按照先序序列顺序插入
{
int a;
cin>>a;
insert(rot,a);
}
inorder(rot);//中序遍历
return 0;
}
拿上面的例子测试一下,先序序列是6 4 1 5 9 8 13,输入程序,然后输出中序遍历结果,可以发现是递增的,至此程序完成了一棵二叉搜索树的建立
二叉树建立
上面学习了特殊二叉树的建立,下面普及到所有的二叉树中
对于一棵普通的树,因为结点值不满足上面左边小,右边大的规则,所以上面的方法不在适用
这时我们可以做一个值的代换,这就是这个算法最精妙的地方
对于上面的树,如果我们按中序遍历的顺序,结点的值用中序遍历先后顺序代替,可以得到下面的这棵树
上面结点的值并不是实际的值,而是代表中序遍历顺序,但是对于上面的这棵树,却满足BST的要求(可以套用上面的建树方法)
值对应关系:
所以我们只需要用map映射好初值和中序顺序值,以结点的中序遍历顺序值为插入判断条件,按照先序序列一个个插入结点即可
用map映射中序序列值,原作者的思路真的厉害,但是一开始理解起来真的很费力==
下面附上实现代码
#include<iostream>
#include<vector>
#include<cstdio>
#include<map>
using namespace std;
struct node{
int data;
node* l;//指向左孩子
node* r;//右孩子
};
map<int,int> indexofbst;
void insert(node* &root,int data)//建树
{
if(root==NULL)//当前位置指向空
{
root=new node;
root->data=data;
root->l=NULL;
root->r=NULL;
}
else
{
if(indexofbst[data]>indexofbst[root->data])insert(root->r,data);//插入右子树
else insert(root->l,data);
}
}
void inorder(node* root)//后序搜索
{
if(root==NULL)return;
inorder(root->l);
inorder(root->r);
cout<<(root->data)<<" ";
}
int main()
{
int n,a;
vector<int> preorder;
cin>>n;
node* rot=NULL;//根结点初始化
for(int i=1;i<=n;i++)//读入中序序列
{
cin>>a;
indexofbst[a]=i;//映射
}
for(int i=1;i<=n;i++)//读入先序序列
{
cin>>a;
preorder.push_back(a);
}
for(int i=0;i<preorder.size();i++)
insert(rot,preorder[i]);
inorder(rot);//后序遍历
return 0;
}
对于上面的树,后序序列是2 7 4 6 3 1 8 5,符合最后的输出