• 树的遍历


    1、结点node定义

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

    2、新建一个结点

    //新建一个结点
    int index=0;
    int newNode(int v){
        Node[index].data=v;
        Node[index].child.clear();  //清空子结点
        return index++;
    }

    3、树的先根遍历

    void PreOrder(int root)
    {
        printf("%d ",Node[root].data);  //访问当前结点
        for(int i=0;i<Node[root].child.size();i++)
        {
            PreOrder(Node[root].child[i]);
        }
    }

    4、树的层序遍历

    void LayerOrder(int root)
    {
        queue<int> Q;
        Q.push(root);
        Node[root].layer=0;
        while(!Q.empty())
        {
            int front=Q.front();
            printf("%d ",Node[front].data);
            Q.pop();
            for(int i=0;i<Node[front].child.size();i++)
            {
                int child=Node[front].child[i];
                Node[child].layer=Node[front].layer+1;
                Q.push(child);
            }
        }
    }

    5、练习题

    PTA 1053 Path of Equal Weight (30 分)

    https://pintia.cn/problem-sets/994805342720868352/problems/994805424153280512

    #include <cstdio>
    #include <vector>
    #include <iostream>
    #include <algorithm>
    #define maxn 105
    using namespace std;
    int n,m;  //结点数量,非叶子结点数量
    int s;    //给定要达到的权值数
    int end_weight=0,end_num=0;
    int path[maxn]={0};
    struct node{
        int weight;  //结点权重值
        vector<int> child;//存放所有子结点下标
    }Node[maxn];
    bool cmp(int a,int b)
    {
        return Node[a].weight>Node[b].weight;
    }
    void DFS(int index,int numNode,int sum);   
    //DFS  三个参数:①当前结点标号index ②当前path数组中结点个数 ③当前权值和sum 
    int main()
    {
        int temp_id,temp_num,value;
        cin>>n>>m>>s;
        for(int i=0;i<n;i++) cin>>Node[i].weight;
        for(int i=0;i<m;i++)
        {
            cin>>temp_id>>temp_num;
            for(int j=0;j<temp_num;j++)
            {
                cin>>value;               //temp_id结点的子结点id值
                Node[temp_id].child.push_back(value);
            }
            sort(Node[temp_id].child.begin(),Node[temp_id].child.end(),cmp);
        }
        path[0]=0;                       //将根结点放入path数组中 
        DFS(0,1,Node[0].weight);    //从根结点root开始,root的下标为0
        return 0;
    }
    void DFS(int index,int numNode,int sum)
    {
        if(sum>s) return;   //若当前权值和大于s,直接返回
        if(sum==s)
        {
            if(Node[index].child.size()!=0) return;  //若sum==s,但是当前结点不是叶子结点,也直接返回
            for(int i=0;i<numNode;i++)
            {
                if(i==0) cout<<Node[path[i]].weight;
                else cout<<" "<<Node[path[i]].weight;
            }
            cout<<endl;
            return;    
        } 
        for(int i=0;i<Node[index].child.size();i++)    //枚举当前结点的所有孩子结点 
        {
            int child=Node[index].child[i];
            path[numNode]=child;    //将当前孩子结点加到path末尾
            DFS(child,numNode+1,sum+Node[child].weight);
        }
    }
    /*
    20 9 24
    10 2 4 3 5 10 2 18 9 7 2 2 1 3 12 1 8 6 2 2
    00 4 01 02 03 04
    02 1 05
    04 2 06 07
    03 3 11 12 13
    06 1 09
    07 2 08 10
    16 1 15
    13 3 14 16 17
    17 2 18 19
    10 5 2 7
    10 4 10
    10 3 3 6 2
    10 3 3 6 2
    
    */

     

    问题A:树查找

    http://codeup.cn/problem.php?cid=100000612&pid=0

    题目描述

    有一棵树,输出某一深度的所有节点,有则输出这些节点,无则输出EMPTY。该树是完全二叉树。

    输入

    输入有多组数据。
    每组输入一个n(1<=n<=1000),然后将树中的这n个节点依次输入,再输入一个d代表深度。

    输出

    输出该树中第d层得所有节点,节点间用空格隔开,最后一个节点后没有空格。

    样例输入 
    5
    1 2 3 4 5 
    7
    7
    1 2 3 4 5 6 7 
    2
    0
    
    样例输出
    EMPTY
    2 3

    思路:根据完全二叉树的性质,首先依据给定n计算二叉树的深度(高度)为log2(n+1) 向上取整或log2n向下取整再加1。再依据给定的深度进行判断,
    若大于树的最大深度,则直接输出EMPTY,
    否则依据第h层树的结点数为[2h-1,min(2h-1,n)]来输出第h层结点元素值;
    x#include <iostream>
    #include <algorithm>
    using namespace std;
    int height(int n);
    int main()
    {
        int n,m,h,hei,value; //n为结点数,m为深度
        while(cin>>n)
        {
            if(n==0) break;
            h=height(n);
            for(int i=0;i<n;i++) cin>>value;
            cin>>hei;
            if(hei>h) cout<<"EMPTY
    ";
            else{
                int last=(n>=(pow(2,hei)-1))?pow(2,hei)-1:n;
                for(int j=pow(2,hei-1);j<=last;j++){
                    if(j!=last) cout<<j<<" ";
                    else cout<<j<<endl;
                }
            }
        }
        return 0;
    }
    int height(int n)
    {
        int value=1;
        int h=0;
        while(value<=n)
        {
            value*=2;
            h++;
        }
        return h;
    }

     

    问题B:树的高度

    一棵树有n个节点,其中1号节点为根节点。

    输入

    第一行是整数n,表示节点数

    后面若干行,每行两个整数a b,表示b是a的子节点。

    输出

    求这棵树的高度(根节点为第1层)

    样例输入 
    5
    1 2
    1 3
    3 4
    3 5
    样例输出
    3
    思路:这题主要在于记录每个结点所在的层号,最后遍历结点编号得到最大的那个层号即为树的层数;这里在构建结点类型时
    添加layer变量来记录每个结点所在的层号,并借助树的层序遍历来
    修改每个结点的层号,即从根结点开始,根结点的层号为1,其所有孩子结点的层号都是在根结点层号基础上加一,
    如此下去直到队列为空,则遍历结束,输出最大的那个层号即为树的总层数;

    #include <cstdio>
    #include <iostream>
    #include <cmath>
    #include <vector>
    #include <queue>
    using namespace std;
    #define maxn 105
    int n,a,b;
    void heig(int root);  //根结点下标
    struct Node{
        int layer;
        vector<int> child;
    }node[maxn];
    int main()
    {
        int h=0;
        cin>>n;
        while(cin>>a>>b)
        {
            node[a].child.push_back(b);
        }
        heig(1);   //根结点下标为1
        for(int i=1;i<=n;i++)
        {
            if(node[i].layer>h) h=node[i].layer;
        }
        cout<<h<<endl;
        return 0;
    }
    //层次遍历树,并计算每个结点的深度
    void heig(int root)
    {
        queue<int> que;
        que.push(root);
        node[root].layer=1;
        while(!que.empty())
        {
            int frot=que.front();
            que.pop();
            for(int i=0;i<node[frot].child.size();i++)
            {
                int id=node[frot].child[i];
                node[id].layer=node[frot].layer+1;
                que.push(id);
            }
        }
    }
     
    天晴了,起飞吧
  • 相关阅读:
    Chrome浏览器与常用插件推荐
    时间戳 转换24小时制
    fis3 开启相对地址
    web手机端禁止滑动,web手机端禁止上下滑动。
    rem的用法
    手机端复制,pc端复制
    ruby 镜像安装
    使用Potree渲染大规模点云-踩坑记录
    移动端真机调试神器-spy-debugger
    手撕Promise.any
  • 原文地址:https://www.cnblogs.com/jianqiao123/p/14391580.html
Copyright © 2020-2023  润新知