描述二叉树
通常我们用一个结构体,来描述二叉树,这样比数组更加方便,可以直接调用左右孩子,以及父亲结点
相关代码:
struct node
{
int p,l,r;//父亲结点,左孩子,右孩子
} T[30];//存放node结点数组
结点深度
在求结点深度时,我们通常用一个D[i]数组表示结点深度,然后从根节点递归求解深度,每次d+1,先考虑递归到底情况!
相关代码:
void setDepth(int u,int d)
{
if(u==NUL)return;//递归到底
D[u]=d;
setDepth(T[u].l,d+1);
setDepth(T[u].r,d+1);
}
结点高度
结点的高度,就是求出左孩子高度,以及右孩子高度取出最高取max即可!
我们仍然采取递归方法,在开始时设置h1,h2表示左右结点的高度,然后递归求出左子树高度,右子树高度,最后取max
相关代码:
int setHeight(int u)
{
int h1=0,h2=0;
if(T[u].l!=NUL)h1=setHeight(T[u].l)+1;
if(T[u].r!=NUL)h2=setHeight(T[u].r)+1;
return H[u]=max(h1,h2);
}
找出兄弟结点
我们先找到父亲结点,再用父亲结点调用左右孩子即可找出兄弟结点
要注意,左孩子的兄弟为右孩子,我们要加在if语句中!
相关代码:
//返回兄弟结点
int getBother(int u)
{
if(T[u].p==NUL) return NUL;//根节点没有兄弟结点
if(T[T[u].p].l!=u&&T[T[u].p].l!=NUL) return T[T[u].p].l;//左孩子的兄弟为右孩子,且不能为NULL
if(T[T[u].p].r!=u&&T[T[u].p].r!=NUL) return T[T[u].p].r;
return NUL;
}
完整代码
输入
n个结点数量,接下来n行输入id,左孩子id,右孩子id
样例输入
9
0 1 4
1 2 3
2 -1 -1
3 -1 -1
4 5 8
5 6 7
6 -1 -1
7 -1 -1
8 -1 -1
输出
结点id,父亲结点,兄弟结点,结点度,深度,高度,结点属性(根节点,内部结点,叶子结点)
完整实现代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn=30;
const int NUL=-1;
int n;
struct node
{
int p,l,r;
} T[30];
int D[maxn],H[maxn];
void setDepth(int u,int d)
{
if(u==NUL)return;//递归到底
D[u]=d;
setDepth(T[u].l,d+1);
setDepth(T[u].r,d+1);
}
int setHeight(int u)
{
int h1=0,h2=0;
if(T[u].l!=NUL)h1=setHeight(T[u].l)+1;
if(T[u].r!=NUL)h2=setHeight(T[u].r)+1;
return H[u]=max(h1,h2);
}
//返回兄弟结点
int getBother(int u)
{
if(T[u].p==NUL) return NUL;//根节点没有兄弟结点
if(T[T[u].p].l!=u&&T[T[u].p].l!=NUL) return T[T[u].p].l;//左孩子的兄弟为右孩子,且不能为NULL
if(T[T[u].p].r!=u&&T[T[u].p].r!=NUL) return T[T[u].p].r;
return NUL;
}
void init()
{
for(int i=0; i<n; i++)
{
T[i].l=T[i].r=T[i].p=NUL;
}
}
void print(int i)
{
int degree=0;
cout<<"node "<<i<<": parent = "<<T[i].p<<", bother = "<<getBother(i)<<", degree=";
if(T[i].l!=NUL) degree++;
if(T[i].r!=NUL) degree++;
cout<<degree<<", depth = "<<D[i]<<", height = "<<H[i]<<", ";
if(T[i].p==NUL)cout<<"root"<<endl;
else if(T[i].l==T[i].r&&T[i].l==NUL)cout<<"leaf"<<endl;
else cout<<"internal node"<<endl;
}
int main()
{
cin>>n;
int id,left,right,parent;
init();
for(int i=0; i<n; i++)
{
cin>>id>>left>>right;
T[i].l=left;
T[i].r=right;
if(left!=NUL)T[left].p=id;
if(right!=NUL)T[right].p=id;
}
for(int i=0; i<n; i++)
{
if(T[i].p==NUL)
{
parent=i;
break;
}
}
setDepth(parent,0);
setHeight(parent);
for(int i=0; i<n; i++)
{
print(i);
}
return 0;
}
二叉树的遍历
二叉树的遍历仍然采用递归实现,前中后遍历都要遍历N个结点所以复杂度都是O(n),只要修改打印语句的位置即可完成前中后的遍历
完整代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn=30;
struct node
{
int p,l,r;
} T[maxn];
void Preorder(int u)
{
if(u==-1)return;
cout<<u<<" ";
Preorder(T[u].l);
Preorder(T[u].r);
}
void Inorder(int u)
{
if(u==-1)return;
Inorder(T[u].l);
cout<<u<<" ";
Inorder(T[u].r);
}
void Postorder(int u)
{
if(u==-1)return;
Postorder(T[u].l);
Postorder(T[u].r);
cout<<u<<" ";
}
int main()
{
int n,left,right,parent,id;
cin>>n;
//初始化
for(int i=0; i<n; i++)
{
T[i].l=T[i].r=T[i].p=-1;
}
//注意结点编号从0开始不是从1开始
for(int i=0; i<n; i++)
{
cin>>id>>left>>right;
T[id].l=left;
T[id].r=right;
if(left!=-1)
{
T[left].p=id;
}
if(right!=-1)
{
T[right].p=id;
}
}
for(int i=0; i<n; i++)
{
if(T[i].p==-1)
{
parent=i;
break;
}
}
cout<<"Preorder"<<endl;
Preorder(parent);
cout<<endl;
cout<<"Inorder"<<endl;
Inorder(parent);
cout<<endl;
cout<<"Postorder"<<endl;
Postorder(parent);
return 0;
}