LCA(Least Common Ancestors)最近公共祖先

LCA(Least Common Ancestors),即最近公共祖先,是指这样一个问题:在有根树中,找出某两个结点u和v最近的公共祖先(另一种说法,离树根最远的公共祖先)。


对于该问题,最容易想到的算法是分别从节点u和v回溯到根节点,获取u和v到根节点的路径P1,P2,其中P1和P2可以看成两条单链表,这就转换成常见的一道面试题:【判断两个单链表是否相交,如果相交,给出相交的第一个点。】。该算法总的复杂度是O(n)(其中n是树节点个数)。



构建上面这个树,求节点F和节点H的最近公共祖先


<pre name="code" class="cpp">#include <stdio.h>
#include <stdlib.h>

struct TreeNode {
    char element;
    struct TreeNode **child;
    unsigned int child_num;
};
typedef struct TreeNode * Tree_t;
struct PathNode {
    char element;
    struct PathNode * next;
};
typedef struct PathNode * Path_list;
Tree_t g_tree;

Path_list dsf(Tree_t tree,Path_list path,char element) {
    unsigned int i;
    Tree_t tmp;
    Path_list tmp_path;
    if(NULL == tree) 
        return;
    //printf("Element is %d\n",tree->element);
    tmp_path = (Path_list)malloc(sizeof(struct PathNode));
    if(tmp_path == NULL) {
        printf("malloc path list error\n");
        exit(-1);
    }
    tmp_path->next = NULL;
    tmp_path->element = tree->element;
    if(path != NULL) {
        path->next = tmp_path;
    }else {
        path = tmp_path;
    }
    if(tree->element == element) {
        return path;
    }
    for(i = 0; i < tree->child_num;i++) {
        tmp = tree->child[i];
        if(NULL != dsf(tmp,tmp_path,element))
            return tmp_path;
        free(tmp_path->next);
        tmp_path->next = NULL;
    }
    return NULL;
}




void main(int argc, char *argv[])
{
    unsigned int i;
    Tree_t tree;
    Tree_t next_tree;
    Path_list path_a,path_b;
    char common_node = 255;

    g_tree = (Tree_t)malloc(sizeof(struct TreeNode));
    if(g_tree == NULL) {
        printf("g_tree malloc error\n");
        return;
    }
    g_tree->element = 'A';
    g_tree->child_num = 2;

    g_tree->child = (Tree_t *)malloc(sizeof(Tree_t));
    for(i = 0; i < 2; i++) {
        g_tree->child[i] = (Tree_t)malloc(sizeof(struct TreeNode));
        if(g_tree->child[i] == NULL) {
            printf("malloc g_tree child error\n");
            exit(-1);
        }
    }
    g_tree->child[0]->element = 'B';
    g_tree->child[0]->child_num = 2;
    g_tree->child[1]->element = 'C';
    g_tree->child[1]->child_num = 0;
    g_tree->child[1]->child = NULL;

    tree = g_tree->child[0];
    tree->child = (Tree_t *)malloc(sizeof(Tree_t)*2);
    for(i = 0; i < 2;i++) {
        tree->child[i] = (Tree_t)malloc(sizeof(struct TreeNode));
        if(tree->child[i] == NULL) {
            printf("malloc tree child error\n");
            exit(-1);
        }
    }
    tree->child[0]->element = 'D';
    tree->child[0]->child_num = 2;

    tree->child[1]->element = 'E';
    tree->child[1]->child_num = 3;

    next_tree = tree->child[0];
    next_tree->child = (Tree_t *)malloc(sizeof(Tree_t)*2);
    for(i = 0; i < 2;i++) {
        next_tree->child[i] = (Tree_t)malloc(sizeof(struct TreeNode));
        if(next_tree->child[i] == NULL) {
            printf("malloc next tree child error\n");
            exit(-1);
        }
    }
    next_tree->child[0]->element = 'F';
    next_tree->child[0]->child_num = 0;
    next_tree->child[1]->element = 'G';
    next_tree->child[1]->child_num = 0;



    next_tree = tree->child[1];
    next_tree->child = (Tree_t *)malloc(sizeof(Tree_t)*3);
    for(i = 0; i < 3;i++) {
        next_tree->child[i] = (Tree_t)malloc(sizeof(struct TreeNode));
        if(next_tree->child[i] == NULL) {
            printf("malloc next tree child error\n");
            exit(-1);
        }
    }


    next_tree->child[0]->element = 'H';
    next_tree->child[0]->child_num = 0;
    next_tree->child[1]->element = 'I';
    next_tree->child[1]->child_num = 0;
    next_tree->child[2]->element = 'J';
    next_tree->child[2]->child_num = 0;


    path_a = NULL;
    path_b = NULL;

    path_a = dsf(g_tree,path_a,'F');
    path_b = dsf(g_tree,path_b,'H');

    while(path_a && path_b && (path_a->element == path_b->element)) {
            common_node = path_a->element;
            path_a = path_a->next;
            path_b = path_b->next;
    }

    if(common_node != 255) {
        printf("find LCA node %c\n",common_node);
    }else {
        printf("no LCA node\n");
    }
    return ;
}

 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值