二叉树相关操作大全

描述二叉树

通常我们用一个结构体,来描述二叉树,这样比数组更加方便,可以直接调用左右孩子,以及父亲结点

相关代码:

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值