转换为C链接剪切树的C ++实现

时间:2017-04-27 22:55:11

标签: c++ c tree graph-algorithm decision-tree

将此实现转换为C代码的最有效方法是什么?我在C ++中真的很棒,我想使用链接切割树,因为它的效率。

#include <cstdio>

using namespace std;

struct Node
{   int sz, label; /* size, label */
    Node *p, *pp, *l, *r; /* parent, path-parent, left, right pointers */
    Node() { p = pp = l = r = 0; }
};

void update(Node *x)
{   x->sz = 1;
    if(x->l) x->sz += x->l->sz;
    if(x->r) x->sz += x->r->sz;
}

void rotr(Node *x)
{   Node *y, *z;
    y = x->p, z = y->p;
    if((y->l = x->r)) y->l->p = y;
    x->r = y, y->p = x;
    if((x->p = z))
    {   if(y == z->l) z->l = x;
        else z->r = x;
    }
    x->pp = y->pp;
    y->pp = 0;
    update(y);
}

void rotl(Node *x)
{   Node *y, *z;
    y = x->p, z = y->p;
    if((y->r = x->l)) y->r->p = y;
    x->l = y, y->p = x;
    if((x->p = z))
    {   if(y == z->l) z->l = x;
        else z->r = x;
    }
    x->pp = y->pp;
    y->pp = 0;
    update(y);
}

void splay(Node *x)
{   Node *y, *z;
    while(x->p)
    {   y = x->p;
        if(y->p == 0)
        {   if(x == y->l) rotr(x);
            else rotl(x);
        }
        else
        {   z = y->p;
            if(y == z->l)
            {   if(x == y->l) rotr(y), rotr(x);
                else rotl(x), rotr(x);
            }
            else
            {   if(x == y->r) rotl(y), rotl(x);
                else rotr(x), rotl(x);
            }
        }
    }
    update(x);
}

Node *access(Node *x)
{   splay(x);
    if(x->r)
    {   x->r->pp = x;
        x->r->p = 0;
        x->r = 0;
        update(x);
    }

    Node *last = x;
    while(x->pp)
    {   Node *y = x->pp;
        last = y;
        splay(y);
        if(y->r)
        {   y->r->pp = y;
            y->r->p = 0;
        }
        y->r = x;
        x->p = y;
        x->pp = 0;
        update(y);
        splay(x);
    }
    return last;
}

Node *root(Node *x)
{   access(x);
    while(x->l) x = x->l;
    splay(x);
    return x;
}

void cut(Node *x)
{   access(x);
    x->l->p = 0;
    x->l = 0;
    update(x);
}

void link(Node *x, Node *y)
{   access(x);
    access(y);
    x->l = y;
    y->p = x;
    update(x);
}

Node *lca(Node *x, Node *y)
{   access(x);
    return access(y);
}

int depth(Node *x)
{   access(x);
    return x->sz - 1;
}

class LinkCut
{   Node *x;

    public:
    LinkCut(int n)
    {   x = new Node[n];
        for(int i = 0; i < n; i++)
        {   x[i].label = i;
            update(&x[i]);
        }
    }

    virtual ~LinkCut()
    {   delete[] x;
    }

    void link(int u, int v)
    {   ::link(&x[u], &x[v]);
    }

    void cut(int u)
    {   ::cut(&x[u]);
    }

    int root(int u)
    {   return ::root(&x[u])->label;
    }

    int depth(int u)
    {   return ::depth(&x[u]);
    }

    int lca(int u, int v)
    {   return ::lca(&x[u], &x[v])->label;
    }
};

int main(void)
{   return 0;
}

描述:link-cut-tree

链接剪切树的C ++实现。链接剪切树数据结构维护受以下操作约束的节点林:

link(x,y):将树植根于x的子树y, cut(x):删除将x连接到其父级的边。 可以使用以下操作查询树:

root(x):找到包含x的树的根, path(x):计算root-to-x路径上节点的函数。 所有操作都需要O(lg n)摊销时间。 root(x)可用于测试连接性。在此实现中,path函数计算其树中节点的深度。可以使用函数lca(x,y)来回答动态最低祖先查询。

接口

  

对于所有0&lt; = x,y&lt; N,

     

LinkCut tree(n); / *带有n个节点的新链接剪切树 / tree.link(x,y);   / 链接x和y / tree.cut(x); / cut x / tree.root(x); / 的根   包含x / tree.depth(x)的树; / 树的x深度 /   tree.lca(x,y); / x和y * /

的最低共同祖先

1 个答案:

答案 0 :(得分:1)

以下是我在C语言中以其当前形式编译的C ++代码可以看到的障碍:

  1. 结构类型Node在各个地方简称为Node,而不是struct Node。通过添加typedef struct Node Node;声明进行修复。
  2. Node有一个构造函数。您可以取消它,只需手动进行初始化。
  3. LinkCut有一个析构函数。这不能用C模拟,所以你可以动态分配所有LinkCut个实例,最后被像void destroy_link_cut_tree(struct LinkCut*)这样的函数销毁,这个函数也会释放Node使用的内存。实例。
  4. LinkCut有一个构造函数。您可以使用struct LinkCut* make_link_cut_tree(int)
  5. 等函数替换它
  6. new用于为Node个对象分配内存。将其替换为malloc并手动进行初始化。
  7. LinkCut具有会员功能。使用带有LinkCut*参数的自由函数替换它们。这也会迫使你给他们提供与个别节点不同的名字,因此你不再需要::来消除歧义。