您的位置:首页 > 其它

二叉树——查找两个随机节点最近的祖先

2015-12-14 21:24 585 查看
非常实用的太久没有一个二叉树,因为需要使用最近,我们觉得非常有必要巩固知识。中间涉及到一个随机算法是寻找两个节点的直接祖先。

我记得和牙石通过,于提出了以下一个方法,网上也有非常多其它的方式实现,再次仅对自己好几个小时的工作作个记录和积累吧!

程序是用C语言写的,个人认为假设用C#实现会更加方便。

首先是数据结构定义:

typedef char TElemType;
typedef bool Status;

typedef struct BiTNode{
TElemType data;
struct BiTNode * lchild, * rchild;
}BiTNode, * BiTree;


其次是建树。用树的定义,以先序序列递归方式建立。

BiTNode * CreateBiTree()
{
char ch;
BiTNode * T;
scanf("%c",&ch);
if(ch=='#')
T = 0;
else
{
T = (BiTree)malloc(sizeof(BiTNode));
T->data = ch;
T->lchild = CreateBiTree();
T->rchild = CreateBiTree();
}
return T;
}


空节点的分隔符本处使用的是“#”,能够用其它字符替代。

查找近期祖先的基本算法是递归。对每一个节点先推断是否有直接关联。都没有就分别获得各自的直系父节点,递归调用时须要通过两个节点的深度来推断下一次调用时用哪个使用父节点。

详细实现例如以下:

//查找两个节点的近期的公共祖先节点
BiTNode * FindNearestAncestor(BiTNode * root, BiTNode* p1, BiTNode* p2, int h1, int h2)
{
if(!p1 || !p2) return 0;
if (p1 == p2)
{
if (p1 == root) return root;
return p1;
}
if (p1 == p2->lchild || p1 == p2->rchild)
return p2;
if (p2 == p1->lchild || p2 == p1->rchild)
return p1;

if (h1 == h2)
return FindNearestAncestor(
root,
GetParent(root, p1),
GetParent(root, p2),
h1 - 1,
h2 - 1);
else
return FindNearestAncestor(
root,
h1 > h2 ? GetParent(root, p1) : p1,
h1 < h2 ?

GetParent(root, p2) : p2,
h1 > h2 ?

h1 - 1 : h1,
h1 < h2 ? h2 - 1 : h2);
}


当中GetParent是获取以root为树根的树中p节点的直系父节点,定义例如以下:

BiTNode * GetParent(BiTNode* root, BiTNode * p)
{
if(!root || p == root) return 0;
if(p == root->lchild || p == root->rchild)
{
return root;
}
else
{
return GetParent(root->lchild, p) == 0 ?

GetParent(root->rchild, p) : GetParent(root->lchild, p);
}
}
在主函数中调用例如以下:

int main()
{
//測试序列: abc###de##fg###
printf("请输入前序序列。空节点用‘#’取代:\n");
BiTree tree = CreateBiTree();
BiTNode * node = FindNearestAncestor(   tree,
tree->rchild->lchild,
tree->rchild->rchild->lchild,
GetHeight(tree,tree->rchild->lchild),
GetHeight(tree,tree->rchild->rchild->lchild)
);

printf("节点%c和节点%c的近期父节点为:%c\n",
tree->rchild->lchild->data,
tree->rchild->rchild->lchild->data,
node->data);
return 0;
}


上述使用了GetHeight函数。用来获取给定树中节点p的高度,这个函数的实现耗费了较多时间。主要是曾经都是获取树的高度,非常少获取指定节点的高度,事实上现例如以下:

//查找节点p的高度。注意与单纯仅仅计算树的高度不同
int GetHeight(BiTNode* root, BiTNode * p, int h = 1)
{
if (!root) return 0;
if (p == root->lchild || p == root->rchild) return h + 1;
return  GetHeight(root->lchild, p, h+1) == 0 ?
GetHeight(root->rchild, p, h+1) : GetHeight(root->lchild, p, h+1);
}


上述測试使用的先序序列为

abc###de##fg###

相应的二叉树例如以下:

a

/ \

b d

/ / \

c e f

/

g

结果例如以下:



只有这个纪录。现在,忘记之后。同时也想和大家分享。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: