有根树的表达_左子右兄弟表示法

这是<<挑战程序设计竞赛2>>上的一节, 介绍了用左子右兄弟的方法存储一棵有根树.

用递归的方法求出所有结点的深度, 复杂度为O(n)

或者是单独求出一个结点的深度(递归或是循环)

以及如何遍历一个结点的所有子结点

#include <bits/stdc++.h>
using namespace std;
#define MAX 1005

struct Node {
    int p, l, r;
} T[MAX];
int D[MAX], n;  //数组D存储树所有节点的深度 

void getDepth(int u, int d)  //u代表结点编号,d代表结点深度 
{
    D[u] = d;
    if(T[u].l != -1) getDepth(T[u].l, d+1);  //是儿子就增加深度 
    if(T[u].r != -1) getDepth(T[u].r, d);  //是兄弟就不增加深度 
} 

void buildTree()  //建立一棵有根树 
{
    int x, y, k, t;
    cin >> n;
    for(int i = 0; i < n; ++i)
        T[i].p = T[i].l = T[i].r = -1;   //刚开始都是没有的,初始化为-1 
    for(int i = 0; i < n; ++i) {
        cin >> x >> k;  //第x个结点,有k个儿子结点 
        for(int j = 0; j < k; ++j) {
            cin >> y;
            if(j == 0) T[x].l = y;  //第一个结点,存储为左子 
            else T[t].r = y;  //其余结点,存储为上一个结点的右兄弟 
            t = y; 
            T[y].p = x;  //所有节点都是x的儿子结点 
        }
    } 
    int root = 0;  //根节点编号 
    for(int i = 0; i < n; ++i)
        if(T[i].p == -1) root = i;
    getDepth(root, 0);  //得到深度数据 
}

void printSon(int u)  //输出儿子结点。从左子开始,迭代遍历其右兄弟 
{
    if(T[u].l != -1) {
        u = T[u].l;
        cout << u;
        while(T[u].r != -1) {
            cout << ", "<< T[u].r;
            u = T[u].r;
        }
    }
}

void printData()  //输出数据 
{
    for(int i = 0; i < n; ++i) {
        cout << "node " << i << ": parent = " << T[i].p << ", depth = " << D[i] << ", ";
        if(T[i].p == -1) cout << "root, [";
        else if(T[i].l == -1) cout << "leaf, [";
        else cout << "internal node, [";
        printSon(i);
        cout << ']';
        cout << endl;
    }
} 

int oneDepth(int u)  //获得一个节点的深度 
{
    if(T[u].p != -1) return oneDepth(T[u].p) + 1;
    else return 0;
}

int main()
{
    buildTree();
    printData();
    cout << "结点5的深度为:" << oneDepth(5) << endl; 
    cout << "结点9的深度为:" << oneDepth(9) << endl; 
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
题目描述 树的表示方法有多种,如图6_1采用的就是一种形象的树形表示法;另外还有一种常用的表示方法"括号表示法",它的表示方法归纳如下:先将整棵树的根结点放入一对圆括号中,然后把它的子树由左至放入括号中,同层子树用圆括号括在一起(同层子树之间用逗号隔开),而对子树也采用同样的方法处理,直到所有的子树都只有一个根结点为止。用括号表示法表示图6_1的步骤如下: =(T) =(1(T1,T2 ,T3 )) {1是根结点,有3棵子树,用逗号隔开} =(1(2(T11,T12),3,4(T31))) {分别对3棵子树做同样的操作} =(1(2(5,6),3,4(7(T311,T312)))) =(1(2(5,6),3,4(7(8,9)))) 实际上,以上方法是按照树的层次逐步展开,直到所有结点都已列出。 注意,当一个节点有若干个子树时,子节点编号小的写在前面,编号大的写在后面。 给你一棵n个节点的有根树,节点标号为1~n,1号节点为根节点。 请给出它的括号表示结果。 输入 第一行一个整数n。 以后n行,每行若干个整数。第i行,第一个数为mi,表示节点i的子节点个数。紧接着mi个整数,表示节点i子节点的编号。保证父节点编号小于子节点。 输出 一行一个字符串,由数字、括号、逗号组成。表示括号表示的结果。注意不包含多余空格。 样例 输入 3 2 2 3 0 0 输出 (1(2,3)) 请用c++语言解决
最新发布
07-15

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值