花了几分钟把之前做的二叉树的建树模板总结了一下,都是很精炼的。
根据先序中序建树,或者根据中序后序建树。
用结构体指针建树的两种方式
不管是根据先序中序,还是中序后序几种方法都可以
用每段长度模拟
核心是根据前序或者后序的根找到中序根的位置,然后对两边分开模拟
const int maxn=1e2+5,inf=0x3f3f3f3f;
typedef long long ll;
ll g[maxn][maxn],pre[maxn];
typedef struct Node *node;
struct Node{
ll val;
node lf,rf;
};
ll zx[maxn],xx[maxn],f=1;
node create(ll zx[],ll xx[],ll len){
if(!len) return nullptr;
else{
node t=new Node({xx[0],nullptr,nullptr});
ll i=0;
while(zx[i++]!=xx[0]);
t->lf=create(zx,xx+1,i-1);
t->rf=create(zx+i,xx+i,len-i);
return t;
}
}
node create(ll hx[],ll zx[],ll len){
if(!len) return nullptr;
else{
node t=new Node({hx[len-1],nullptr,nullptr});
ll i=0;
while(zx[i++]!=hx[len-1]);
t->lf=create(hx,zx,i-1);
t->rf=create(hx+i-1,zx+i,len-i);
return t;
}
}
用每段的位置模拟
核心是根据前序或者后序的根找到中序根的位置,然后对两边分开模拟
const int maxn=1e2+5,inf=0x3f3f3f3f;
typedef long long ll;
ll g[maxn][maxn],pre[maxn];
typedef struct Node *node;
struct Node{
ll val;
node lf,rf;
};
ll zx[maxn],xx[maxn],f=1;
node create(ll inl,ll inr,ll firl,ll firr){
if(inl>inr)
return nullptr;
node t=new Node({xx[firl],nullptr,nullptr});
ll i=1;
while(zx[i]!=xx[firl]) i++;
ll len=i-inl;
t->lf=create(inl,i-1,firl+1,firl+len);
t->rf=create(i+1,inr,firl+len+1,firr);
return t;
}
node create(ll postl,ll postr,ll inl,ll inr){
if(postl>postr) return nullptr;
else{
node t=new Node({hx[postr],nullptr,nullptr});
ll i=0;
while(zx[i]!=hx[postr]) i++;
ll num=i-inl;
t->lf=create(postl,postl+num-1,inl,i-1);
t->rf=create(postl+num,postr-1,i+1,inr);
return t;
}
}
用数组模拟层序遍历
vector<int>in,pre,level(1000000,-1);
void levelorder(int root,int start,int end,int index)
{
if(start>end) return ;
int i=start;
while(i<end&&pre[root]!=in[i]) i++;
level[index]=pre[root];
levelorder(root+1,start,i-1,2*index+2);
//这个+2是根据题目中要求的,我这个题目是反序层次遍历,当然这俩顺序可以换一下。看题目中要求
levelorder(root+1+i-start,i+1,end,2*index+1);
}
用数组模拟某序遍历
vector<int>in,pre,level(1000000,-1);
void levelorder(int root,int start,int end)
{
if(start>end) return ;
int i=start;
while(i<end&&pre[root]!=in[i]) i++;
// 换成输出就可以了
levelorder(root+1,start,i-1);
levelorder(root+1+i-start,i+1,end);
}
用数组模拟二叉搜索树
// idx 需要从 1 开始
void build(int idx,int x)
{
if(a[idx]==0) a[idx]=x;
else if(x>a[idx]) build(idx<<1|1,x);
// <<1 相当于乘2, |1相当于+1
else if(x<a[idx]) build(idx<<1,x);
}
平衡二叉树
#include<bits/stdc++.h>
#define rep(i,a,b) for(ll i=(a);i<=(b);++i)
#define per(i,a,b) for(ll i=(a);i>=(b);--i)
#define pb push_back
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
typedef struct Node *node;
struct Node{
ll val;
node lf,rf;
};
ll Gh(node t){
if(!t) return 0;
else{
ll l,r;
l=Gh(t->lf);
r=Gh(t->rf);
return l>r?++l:++r;
}
}
node turnleft(node t){
node r=t->rf;
t->rf=r->lf;
r->lf=t;
return r;
}
node turnright(node t){
node r=t->lf;
t->lf=r->rf;
r->rf=t;
return r;
}
node turnleftright(node t){
t->lf=turnleft(t->lf);
return turnright(t);
}
node turnrightleft(node t){
t->rf=turnright(t->rf);
return turnleft(t);
}
node insert(node t,ll x){
if(!t) t=new Node({x,nullptr,nullptr});
else{
if(x<t->val){
t->lf=insert(t->lf,x);
if(Gh(t->lf)-Gh(t->rf)==2){
if(x<t->lf->val)
t=turnright(t);
else
t=turnleftright(t);
}
}
else{
t->rf=insert(t->rf,x);
if(Gh(t->rf)-Gh(t->lf)==2){
if(t->rf->val<x)
t=turnleft(t);
else
t=turnrightleft(t);
}
}
}
return t;
}
int main(){
ll n,x;
node t=nullptr;
cin >> n;
rep(i,0,n-1){
cin >> x;
t=insert(t,x);
}
cout << t->val;
return 0;
}
根据二叉搜索树构建平衡二叉树
#include<bits/stdc++.h>
using namespace std;
static const int maxn=1e5;
typedef struct Node *node;
struct Node{
int val;
node lf,rf;
};
int a[maxn],cnt=0;
void dfs(node t){
if(t){
dfs(t->lf);
a[cnt++]=t->val;
dfs(t->rf);
}
}
node build(int l,int r){
if(l>r)
return nullptr;
int mid=(l+r)/2;
node t=new Node({a[mid],nullptr,nullptr});
t->lf=build(l,mid-1);
t->rf=build(mid+1,r);
return t;
}
int main() {
node root;
//构建root,root为普通的二叉搜索树
dfs(root);
node t=build(0,cnt-1); // cnt为r的节点个数,cnt-1为最后一个的下标
//t为平衡二叉树
return 0;
}