二叉树——查找两个任意节点的最近祖先

很久没有用过二叉树了,最近由于需要用到了,发现很多知识需要巩固了,中间涉及到一个算法就是找任意两个节点的最近祖先。通过本人回顾和演算,最终提出了下面一个方法,网上也有很多其他的方式实现,再次仅对自己好几个小时的工作作个记录和积累吧!
程序是用C语言写的,个人觉得如果用C#实现会更加方便。

首先是数据结构定义:

[cpp] view plaincopyprint?

  1. typedef char TElemType;

  2. typedef bool Status;
  3. typedef struct BiTNode{

  4. TElemType data;

  5. struct BiTNode * lchild, * rchild;

  6. }BiTNode, * BiTree;

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

[cpp] view plaincopyprint?

  1. BiTNode * CreateBiTree()

  2. {

  3. char ch;

  4. BiTNode * T;

  5. scanf("%c",&ch);

  6. if(ch==‘#‘)

  7. T = 0;

  8. else

  9. {

  10. T = (BiTree)malloc(sizeof(BiTNode));

  11. T->data = ch;

  12. T->lchild = CreateBiTree();

  13. T->rchild = CreateBiTree();

  14. }

  15. return T;

  16. }

空节点的分隔符本处使用的是“#”,可以用其他字符替代。

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

[cpp] view plaincopyprint?

  1. //查找两个节点的最近的公共祖先节点

  2. BiTNode * FindNearestAncestor(BiTNode * root, BiTNode* p1, BiTNode* p2, int h1, int h2)

  3. {

  4. if(!p1 || !p2) return 0;

  5. if (p1 == p2)

  6. {

  7. if (p1 == root) return root;

  8. return p1;

  9. }

  10. if (p1 == p2->lchild || p1 == p2->rchild)

  11. return p2;

  12. if (p2 == p1->lchild || p2 == p1->rchild)

  13. return p1;
  14. if (h1 == h2)

  15. return FindNearestAncestor(

  16. root,

  17. GetParent(root, p1),

  18. GetParent(root, p2),

  19. h1 - 1,

  20. h2 - 1);

  21. else

  22. return FindNearestAncestor(

  23. root,

  24. h1 > h2 ? GetParent(root, p1) : p1,

  25. h1 < h2 ? GetParent(root, p2) : p2,

  26. h1 > h2 ? h1 - 1 : h1,

  27. h1 < h2 ? h2 - 1 : h2);

  28. }

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

[cpp] view plaincopyprint?

  1. BiTNode * GetParent(BiTNode* root, BiTNode * p)

  2. {

  3. if(!root || p == root) return 0;

  4. if(p == root->lchild || p == root->rchild)

  5. {

  6. return root;

  7. }

  8. else

  9. {

  10. return GetParent(root->lchild, p) == 0 ?

  11. GetParent(root->rchild, p) : GetParent(root->lchild, p);

  12. }

  13. }

在主函数中调用如下:

[csharp] view plaincopyprint?

  1. int main()

  2. {

  3. //测试序列: abc###de##fg###

  4. printf("请输入前序序列,空节点用‘#’代替:\n");

  5. BiTree tree = CreateBiTree();

  6. BiTNode * node = FindNearestAncestor(   tree,

  7. tree->rchild->lchild,

  8. tree->rchild->rchild->lchild,

  9. GetHeight(tree,tree->rchild->lchild),

  10. GetHeight(tree,tree->rchild->rchild->lchild)

  11. );
  12. printf("节点%c和节点%c的最近父节点为:%c\n",

  13. tree->rchild->lchild->data,

  14. tree->rchild->rchild->lchild->data,

  15. node->data);

  16. return 0;

  17. }

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

[cpp] view plaincopyprint?

  1. //查找节点p的高度,注意与单纯只计算树的高度不同

  2. int GetHeight(BiTNode* root, BiTNode * p, int h = 1)

  3. {

  4. if (!root) return 0;

  5. if (p == root->lchild || p == root->rchild) return h + 1;

  6. return  GetHeight(root->lchild, p, h+1) == 0 ?

  7. GetHeight(root->rchild, p, h+1) : GetHeight(root->lchild, p, h+1);

  8. }

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

abc###de##fg###

对应的二叉树如下:

a

/      \

b        
 d
         /        
  /    \

c           e    
  f

/

g

结果如下:

仅此记录,供以后忘记了查阅,同时也希望和大家分享。

二叉树——查找两个任意节点的最近祖先,码迷,mamicode.com

时间: 2024-10-17 07:21:48

二叉树——查找两个任意节点的最近祖先的相关文章

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

非常实用的太久没有一个二叉树,因为需要使用最近,我们觉得非常有必要巩固知识.中间涉及到一个随机算法是寻找两个节点的直接祖先. 我记得和牙石通过,于提出了以下一个方法,网上也有非常多其它的方式实现,再次仅对自己好几个小时的工作作个记录和积累吧! 程序是用C语言写的,个人认为假设用C#实现会更加方便. 首先是数据结构定义: typedef char TElemType; typedef bool Status; typedef struct BiTNode{ TElemType data; stru

二叉树中两个结点最近的公共祖先汇总

一.若二叉树为搜索二叉树 原题链接:https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/#/description Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST. According to the definition of LCA on

习题整理,二叉树后续遍历得到指定节点到其祖先的路径

原文地址:https://www.cnblogs.com/yuelien/p/10051254.html

二叉树(12)----查找两个节点最低祖先节点(或最近公共父节点等),递归和非递归

1.二叉树定义: typedef struct BTreeNodeElement_t_ { void *data; } BTreeNodeElement_t; typedef struct BTreeNode_t_ { BTreeNodeElement_t *m_pElemt; struct BTreeNode_t_ *m_pLeft; struct BTreeNode_t_ *m_pRight; } BTreeNode_t; 2.查找二叉树中两个节点的最低祖先节点(或最近公共父节点等) 最低祖

二叉树求两节点最低公共祖先,求随意两节点距离

-------1.求最低公共祖先LCA( Lowest Common Ancestor ) 什么是最低公共祖先?例如以下图.2与3的LCA是1:1与4的LCA是1:4与5的LCA是2. 那么给定两个节点n1和n2,如今要找出它们的LCA,怎样找?首先分析一下,n1和n2有几种情况?第一种.n1和n2分别在一个节点的左右子树中,比方4和5,LCA就是2,5和6,LCA就是1.2和3,LCA就是1:另外一种.n1和n2都在左子树或右子树,比方2和4,LCA就是2,1和4.LCA就是1. 一共这两种情

LeetCode 530. Minimum Absolute Difference in BST(在二叉查找树中查找两个节点之差的最小绝对值)

题意:在二叉查找树中查找两个节点之差的最小绝对值 /** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: int ans = 0x3f3f3f3f; TreeNo

二棵树某两个节点的公共祖先。

1. 如果是有parent指针的树,可以转化成 求两个链表第一个公共节点的问题. 对于无parent指针普通二叉树(假定这两个节点一定在树中,否则需要先遍历一边树查找是否存在该节点) 1. (剑指offer的解法),先用一定的空间记录从根节点到两个节点各自的路径,然后找这两个路径最后一个相交的节点. 2.  CC150,递归求解. TreeNode commonAncestor(TreeNode root, TreeNode p, TreeNode q){ } 二棵树某两个节点的公共祖先.,布布

递归函数的设计--以二叉树查找为例

工作后发现,大学计算机课程里面的树结构相当有用,很多现实中的东西把它看成树就容易理解多了. ----大学舍友 最近和二叉树有关的代码频繁地打交道.由于函数的递归实现占用巨大的计算机运行时间(尤其是深层递归调用,存储函数参数的程序栈会占据很大的运行时间,参见图1),我的目的是将递归实现改为非递归的循环实现(以前的编程经验表明,两者的运行速度相差悬殊).本文以二叉树查找为例,对递归函数的设计进行分析说明,最后给出查找的非递归实现思路. 图1. 递归调用示意图 递归,就是函数调用自身的一种方式[1].

查找二,二叉树查找与2-3树红黑树

BST: 每个节点的键,都大于其左自述中的任意节点的键,而小于有字数的任意结点的键. 部分实现 get(Node x , Key key){ if(x == null) return null; cmp = key.compareTo(x.key); if(cmp<0) retrun get(x.right,key); else if(cmp>0) retrun get(x.left,key); else return x.val; } 2-3树红黑树: 属于平衡查找树,为了希望保持二分查找树