二叉树构建的各种方法

花了几分钟把之前做的二叉树的建树模板总结了一下,都是很精炼的。

根据先序中序建树,或者根据中序后序建树。

用结构体指针建树的两种方式

不管是根据先序中序,还是中序后序几种方法都可以

用每段长度模拟
核心是根据前序或者后序的根找到中序根的位置,然后对两边分开模拟

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;
}
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值