树
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+2n2。所以,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;
}