1.Rooted Tree(有根树)

//左子右兄弟表示法
struct Node{int parent, left, right};
struct Node T[MAX];
//else
int parent[MAX],left[MAX],right[MAX];
//规定:
//parent 结点u的父节点,没有父节点的为根结点;
//left为节点u的最左侧的子结点,没有左子结点的为叶节点
//right右侧紧邻的兄弟结点
//NIL表示parent,left,right都没有的得情况,一般以-1表示
#include<iostream>
#define MAX 100005
#define NIL -1
using namespace std;
struct Node{
	int parent;
	int left;
	int right;
};

Node T[MAX];
int D[MAX];
/*int depth(int u)//从u回溯至根结点,统计经过的边数
{
	int d=0;
	while(T[u].parent!=NIL)
	{
		u=T[u].parent;
		d++;
	}
	return d; 
}*/

int setdepth(int u, int p)//递深度归求所有结点的
{
	D[u]=p;//一般u=0,p=0;
	if(T[u].right != NIL)setdepth(T[u].right,p);
	if(T[u].left != NIL)setdepth(T[u].left,p+1);	
}

void print(int u)//打印树,u=root
{
	int i,c;
	cout<<"node "<< u<<": ";
	cout<<"parent = "<<T[u].parent<<", ";
	cout<<"depth = "<<D[u]<<", ";
	if(T[u].parent==NIL)cout<<"root, ";
	else if(T[u].left==NIL)cout<<"leaf, ";
	else cout<<"internal node, ";
	cout<<"[";
	for(int i=0,c=T[u].left; c!=NIL; i++, c=T[c].right)
	{
		if(i)cout<<", ";
		cout<<c;
	}
	cout<<"]"<<endl;
}

int main()
{
	int n,v,d,c,l,root;
	cin>>n;
	for(int i=0;i<n;i++) T[i].left=T[i].right=T[i].parent=NIL;
	for(int i=0;i<n;i++)
	{
		cin>>v>>d;//v,结点编号0-n-1,d为度数
		for(int j=0;j<d;j++)
		{
			cin>>c;//子结点
			if(j==0)T[v].left=c;//v的左子结点为c
			else T[l].right=c;//l的即上一个子结点
			l=c;
			T[c].parent=v;
		}
	}

	for(int i=0;i<n;i++)
	{
		if(T[i].parent==NIL)root=i;
	}
	setdepth(root, 0);
	for(int i=0; i<n; i++)
	{
		print(i);
	}
	return 0;
}

二.二叉树的表达
性质:
(1)二叉树中,第 i 层最多有 2i-1 个结点。
(2)如果二叉树的深度为 K,那么此二叉树最多有 2K-1 个结点。
(3)二叉树中,终端结点数(叶子结点数)为 n0,度为 2 的结点数为 n2,则 n0=n2+1。

性质 3 的计算方法为:对于一个二叉树来说,除了度为 0 的叶子结点和度为 2 的结点,剩下的就是度为 1 的结点(设为 n1),那么总结点 n=n0+n1+n2。
同时,对于每一个结点来说都是由其父结点分支表示的,假设树中分枝数为 B,那么总结点数 n=B+1。而分枝数是可以通过 n1 和 n2 表示的,即 B=n1+2
n2。所以,n 用另外一种方式表示为 n=n1+2n2+1。
两种方式得到的 n 值组成一个方程组,就可以得出 n0=n2+1。

数据结构深度为k的完全二叉树,高度为k+1,也就是说有k+1层。
1数组实现

struct Node{
int parent, left, right;
};
//在这里,left为左子结点,right为右子结点 没有左/右子结点是为NIL=-1
#include<cstdio>
#define MAX 100000
#define NIL -1
using namespace std;
struct Node{
	int parent;
	int left;
	int right;
};
Node T[MAX];
int n, D[MAX],H[MAX];

int setHeight(int u)//递归求高度
{
	int h1=0,h2=0;
	if(T[u].left!=NIL)h1=setHeight(T[u].left)+1;//求左子树
	if(T[u].right!=NIL)h2=setHeight(T[u].right)+1;//右子树
	return H[u] = (h1>h2?h1:h2);
}

void setdepth(int u, int p)//u=root=0,p=0;
{
	if(u==NIL) return;//空树
	D[u]=p;
	setdepth(T[u].left, p+1);
	setdepth(T[u].right, p+1);
}

int getsibling(int u)//返回结点u的兄弟结点
{
	if(T[u].parent==NIL) return NIL;//根结点无兄弟结点
	else if(T[T[u].parent].left!=u && T[T[u].parent].left!=NIL)//u的兄弟结点为u的父节点的left
	{
		return T[T[u].parent].left;
	}
	else if(T[T[u].parent].right!=u && T[T[u].parent].right!=NIL)//同理
	{
		return T[T[u].parent].right;
	}
	return NIL;
}

void print(int u)
{
	printf("node %d: ",u);
	printf("parent = %d, ",T[u].parent);
	printf("sibling = %d, ",getsibling(u));
	int deg=0;
	if(T[u].left != NIL) deg++;
	if(T[u].right != NIL) deg++;
	printf("degree = %d, ",deg);
	printf("depth = %d, ",D[u]);
	printf("height = %d, ",H[u]);
	if(T[u].parent==NIL)
	{
		printf("root\n");
	}
	else if(T[u].left==NIL&&T[u].right==NIL)
	{
		printf("leaf\n");
	}
	else printf("internal node\n");
} 

int main()
{
	int v,l,r,root=0;
	scanf("%d",&n);
	for(int i=0;i<n;i++)
	{
		T[i].parent=T[i].left=T[i].right=NIL;
	 } 
	 for(int i=0;i<n;i++)
	 {
	 	scanf("%d %d %d",&v,&l,&r);
	 	T[v].left=l;
	 	T[v].right=r;
	 	if(l!=NIL) T[l].parent=v;
	 	if(r!=NIL) T[r].parent=v;
	 }
	 for(int i=0;i<n;i++)
	 {
	 	if(T[i].parent==NIL) root=i;
	 }
	 setdepth(root,0);
	 setHeight(root);
	 for(int i=0;i<n;i++) print(i);
	 return 0;
}

2链表实现

在这里插入代码片

3树的遍历

#include<cstdio>
using namespace std;
#define MAX 10000
#define NIL -1

struct node{
	int p;
	int l;
	int r;
};
node T[MAX];
int n;

void preParse(int u)//前序遍历
{
	if(u==NIL) return;
	printf(" %d", u);
	preParse(T[u].l);
	preParse(T[u].r);
}

void inParse(int u)
{
	if(u==NIL) return;//中序遍历
	inParse(T[u].l);
	printf(" %d",u);
	inParse(T[u].r);
}

void postParse(int u)
{
	if(u==NIL) return;//后序遍历
	postParse(T[u].l);
	postParse(T[u].r);
	printf(" %d",u);
}
int main()
{
	int v,l,r,root;
	scanf("%d",&n);
	for(int i=0;i<n;i++) T[i].l=T[i].p=T[i].r=NIL;
	for(int i=0;i<n;i++)
	{
		scanf("%d %d %d",&v,&l,&r);
		T[v].l=l;
		T[v].r=r;
		if(l!=NIL)T[l].p=v;
		if(r!=NIL)T[r].p=v;
	}
	
	for(int i=0;i<n;i++)
	if(T[i].p==NIL)root=i;
	
	printf("Preorder\n");
	preParse(root);
	printf("\n");
	printf("Inorder\n");
	inParse(root);
	printf("\n");
	printf("Postorder\n");
	postParse(root);
	printf("\n");
	return 0;	
}

4.Reconstruction of the Tree

#include<bits/stdc++.h>
using namespace std;
#define MAX
int n,pos;
vector<int>pre,in,post;

void rec(int l,int r)
{
	if(l>=r) return;
	int root=pre[pos++];//找到当前根节点 
	int m=distance(in.begin(),find(in.begin(),in.end(),root));//当前节点的左子树 
	rec(l,m);//左子树递归 
	rec(m+1,r);//右子树递归
	post.push_back(root);
}
void solve()//后序输出
{
	pos=0;//设置根结点
	rec(0,pre.size());
	for(int i=0;i<post.size();i++)
	{
		if(i)cout<<" ";
		cout<<post[i];
	}
	cout<<endl;
}

int main()
{
	int k;
	cin>>n;
	for(int i=0;i<n;i++)//前序遍历输入

	{
		cin>>k;
		pre.push_back(k);
	}
	for(int i=0;i<n;i++)//中序遍历输入,前序遍历的结点c 在中序遍历中的位置的左侧为左子树,右侧为右子树
	{
		cin>>k;
		in.push_back(k);
	}
	
	solve();
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值