算法 {删除树的叶节点}

算法 {删除树的叶节点}

删除树的叶节点

算法

通过度数来删除

代码
{ // 删除树的所有*叶节点*
    auto const& __Tree = Graph;
    int N = __Tree.PointsCount;
    ASSERT_MSG_( "tree是*无向树*, 且没有*重复边*");
    vector<int> __Degree; // `Degree[x]`表示`x`的邻接点的个数; (如果等于`-1` 说明该点被删除了已经);
    //< 只有`Degree[x] != -1`的点 是存在的点(否则是已经删除的点); 对于边`a-b`(如果`a,b`点都存在 则该边才存在);  因为`Tree`我们不会修改他 因此借用`Degree[x]` 来表示*删除节点*这个操作;
    //  . 获取当前的新树的所有点: `FOR_( i,0,N-1){ if(__Degree[i]!=-1){ DE_(i);}}`; (注意*孤立点*这种情况, 其`Degree[]==0` 没有临界边 但他是存在的 而不是已删除);
    //  . 获取当前的新树的所有边: `FOR_( i, 0, N-1){ if(__Degree[i]==-1){continue;} GRAPH_ITERATE_( __Tree,i,nex,e){ if(__Degree[nex]==-1){continue;} DE_(i,nex);}}`;
    __Degree.resize( N);
    std::memset( __Degree.data(), 0, sizeof(__Degree[0])*N);
    for( int i = 0; i < N; ++i){ GRAPH_ITERATE_( __Tree, i, nex, e){ __Degree[nex] ++;}}

    auto __Delete = [&](){ // 每次调用该函数 就会删除*一层叶节点*;
        static std::queue<int> __Que;
        while( !__Que.empty()){ __Que.pop();}
        for( int i = 0; i < N; ++i){
            if( __Degree[i] == 0){ // 孤立点(他也属于*叶节点*)
                __Degree[i] = -1; // 直接删除
            }
            else if( __Degree[i] == 1){ // 叶节点(且不是孤立点)
                __Que.push( i);
            }
        }
        while( 0 == __Que.empty()){
            auto leaf = __Que.front();  __Que.pop(); // `leaf`一定是叶节点
            __Degree[leaf] = -1; // 表示删除了`leaf`这个节点;
            GRAPH_ITERATE_( __Tree, leaf, nex, e){
                if( __Degree[nex] == -1){ continue;} // 表示`nex`已经被删除了;
                -- __Degree[nex]; // 这表示删除了`leaf-nex`这条边
                
                { // 递归删除 (如果产生了新的叶节点, 就继续删除)
                    @TODO;
                    if( __Degree[nex] == 0){ // 孤立点(他也属于*叶节点*)
                        __Degree[nex] = -1; // 直接删除
                    }
                    else if( __Degree[nex] == 1){ // 叶节点(且不是孤立点)
                        __Que.push( nex); // 新的叶子节点
                    }
                }
            }
        }
    };
    
    @TODO: __Delete();
} // 删除树的所有*叶节点*

应用

@LINK: https://editor.csdn.net/md/?articleId=129839971;
递归的删除(即如果删除新叶节点 继续删除), 且只有满足某种条件的叶节点 才考虑删除;

错误

删除所有的叶节点和其父节点, 与, 执行两次(删除叶节点), 他俩的效果一样吗?
不一样, 比如X-a-b-c-Y, b-Z, 执行两次(删除叶节点) 得到b; 而删除所有叶节点和其父节点 得到;
因为, 你认为叶节点的父节点 就是 删除叶节点后的叶节点, 这是错误的, 你即便把叶节点给删除了, 他的父节点 不一定就是新树的叶节点;

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值