《算法笔记》9.3 树的遍历

9.3 树的遍历

9.3.1 树的静态写法

这里的“树”指的是一般意义上的树,即子节点个数不限且子节点没有先后次序的树。

struct node{
    typename data ; //数据域
    vector<int> child ; //指针域,存放当前节点所有子节点下标
}Node[maxn];        //节点数组,maxn为节点上限个数

一般都是很人性化地给出了结点的编号,并且编号一定是0,1,…N-1(其中N为结点个数)或是1,2,.,N。在这种情况下,就不需要newNode函数了,因为题目中给定的编号可以直接作为Node数组的下标使用,非常方便。作为示例:
image.png

//vo: 
Node[0].child [0] = 1, Node[0].child[1] = 2, Node[0].child[2] =3; 
//V1: 
Node[1].child[0] = 4, Node[1].child[1] = 5; 
//v2: 
Node[2] has no children, so Node[2].child.size () == 0; 
//v3: 
Node[3].child[0] = 6; 
//v4: 
Node[4] has no children, so Node[4].child.size()== 0; 
//V5: 
Node[5] has no children, so Node[5].child.size() == 0; 
//v6: 
Node[6] has no children, so Node[6].child.size() == 0;

9.3.2 树的先根遍历

对一棵一般意义的树来说,也可以采用类似二叉树的思路来进行遍历。
image.png
先跟序列为0145236

void preOrder( int root ){
    cout << Node[root].data <<endl ;
    for( int i = 0 ; i < Node[root].child.size() ; i++ ){
        preOrder( Node[root].child[i] ) ;   //递归访问当前节点root的所有子节点
    }

}

9.3.3 树的层序遍历

树的层序遍历的实现方法与二叉树类似,一般使用一个队列来存放节点再数组中的下标,每次取出队首元素来访问,并将其所有子节点加入队列,直到队列为空。

//层序遍历树
void LayerOrder( int root ){
    queue<int> q ;
    q.push(root) ;
    
    while( !q.empty() ){
        int top = q.front() ;
        q.pop() ;
        cout << Node[top].data << endl ;
        for( int i = 0 ; i < Node[top].child.size() ; i++ ){
            q.push( Node[top].child[i] ) ;      //将当前节点的所有子节点入队
        }
    }
}

同样的,如果需要对节点的层号进行求解,只需要在结构体node定义中增加变量来记录节点的层号:

struct node{
    typename data ; //数据域
    int layer;  //层号
    vector<int> child ; //指针域,存放当前节点所有子节点下标
}Node[maxn];        //节点数组,maxn为节点上限个数

于是树的遍历就可以写成:

void LayerOrder( int root ){
    queue<int> q ;
    q.push(root) ;
    Node[root].layer = 1 ;  //记录根结点的层号
    while( !q.empty() ){
        int top = q.front() ;
        q.pop() ;
        cout << Node[top].data << endl ;
        for( int i = 0 ; i < Node[top].child.size() ; i++ ){
            int child = Node[top].child[i] ;
            Node[child].layer = Node[top].layer + 1 ;
            q.push( Node[top].child[i] ) ;      //将当前节点的所有子节点入队
        }
    }
}

9.3.4 从树的遍历看DFS与BFS

DFS与先跟

对所有合法的DFS求解过程,都可以把它画成树的形式,此时死胡同等价于树中的叶子结点,而岔道口等价于树中的非叶子节点,并且对这棵树的DFS遍历过程就是树的先跟遍历过程。

于是可以从中得到启发:碰到一些可以用DFS做的题目,不妨把一些状态作为树的结点,然后问题就会转换为直观的对树进行先根遍历的问题。如果想要得到树的某些信息,也可以借用DFS以深度作为第一关键词的思想来对结点进行遍历,以获得所需的结果。例如求解叶子结点的带权路径和(即从根结点到叶子结点的路径上的结点点权之和)时就可以把到达死胡同作为一条路径结束的判断。

BFS与层序遍历

事实上,对所有合法的BFS求解过程,都可以像DFS中那样画出一棵树,并且将广度优先搜索问题转换为树的层序遍历的问题。

例题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值