二叉树中两个节点的最近公共祖先节点方法全集
2016-06-15 21:28
381 查看
一.如果数据结构为三叉链表,即含有指向父节点的指针:
以上方法叫双重循环法,上面的算法实际上是将一个结点回退到父结点,每退一步,另一个结点指针将回退到不能退为止。此过程来判断它们两结点是否有共同的父母。
二.如果为二叉搜索树中找出两节点的最近祖先节点
[b]检查当前节点;如果value1和value2都小于当前节点的值,检查它的左子节点;如果value1和value2都大于当前节点的值,检查它的右子节点;否则,当前节点就是最近共同祖先。
[/b]
三.如果是普通二叉树
思想
活用Hash表:
如果每个节点有指向父节点的指针,那么逆向遍历两个节点的所有祖先节点,找第一个一样的祖先,可用hash表存储,
时间复杂度是树的深度,空间复杂度也是数的深度。
可以将q到头结点建立一张Hash表,然后从p到头结点,边遍历边查找Hash表,直到第一次在hash表在哦个查找到节点值存在。
(其实我们可以简单的过程来看思想二的算法:我们可以开辟指向节点的指针数组,先从一个节点下手,让它一直回退,每退一步,数组新的位置记录下它,即指向该节点,直到第一个节点回退完,再进行第二个节点的回退,每退一步就检查一下它在数组中有没有,这样和思想一是一样的,故为了加速,这里应该将每一个节点的回退过程的地址扔进hashset里去,在回退第二个节点时,查一下hashset里有没有此节点,有则找到所以的祖先节点,没有就继续找)
Node * NearestCommonAncestor(Node * root,Node * p,Node * q) { Node * temp; while(p!=NULL) { p=p->parent; temp=q; while(temp!=NULL) { if(p==temp->parent) return p; temp=temp->parent; } } }
以上方法叫双重循环法,上面的算法实际上是将一个结点回退到父结点,每退一步,另一个结点指针将回退到不能退为止。此过程来判断它们两结点是否有共同的父母。
二.如果为二叉搜索树中找出两节点的最近祖先节点
[b]检查当前节点;如果value1和value2都小于当前节点的值,检查它的左子节点;如果value1和value2都大于当前节点的值,检查它的右子节点;否则,当前节点就是最近共同祖先。
[/b]
Node* findLowerstCommonAncestor(Node* root, int value1, int value2) { while ( root != NULL ) { int value = root->getValue(); if ( value > value1 && value > value2 ) root = root->getLeft(); else if (value < value1 && value < value2) root = root->getRight(); else return root; } return NULL; }
三.如果是普通二叉树
bool Getpath(BinaryTreeNode<int>* root,BinaryTreeNode<int>* str1, list<BinaryTreeNode<int>*>& List) //寻找路径 { if(root == NULL || str1 == NULL) //如果其中的一个为空,便不成立 return false; if(root == str1) //如果第一个就是,并且与跟节点相同,便返回 { List.push_back(root); return true; } List.push_back(root);//先压左 bool juge = Getpath(root->_left,str1,List); if(!juge) //在左不成立的情况下,才压右
juge = Getpath(root->_right,str1,List); if(!juge) //把不成立的数据弹出 List.pop_back(); return juge; } BinaryTreeNode<int>* CommonAncestor(BinaryTreeNode<int>* root,BinaryTreeNode<int>* str1, BinaryTreeNode<int>* str2) { assert(root); assert(str1); assert(str2); //断言,确保传值 if(root == NULL || str1 == NULL || str2 ==NULL) //判断条件是否成立 return NULL; if(root == str1 || root == str2) //如果根节点等于其中的一个,便说明,没有公共祖先节点 return NULL; list<BinaryTreeNode<int>*> List1; list<BinaryTreeNode<int>*> List2; bool juge1 = Getpath(root,str1,List1); bool juge2 = Getpath(root,str2,List2); if(juge1 == false || juge2 == false) return NULL; BinaryTreeNode<int> * commonParent=NULL; list<BinaryTreeNode<int>*>::iterator ite1=List1.begin(); list<BinaryTreeNode<int>*>::iterator ite2=List2.begin(); for(;ite1!=List1.end() && ite2!=List2.end();ite1++,ite2++) //寻找最近公共节点 { if(*ite1==*ite2) commonParent=*ite1; else break; } return commonParent; }此处借用了队列的用法,把到两个节点的路径分别加入到两个队列中,因为都是从根向下遍历,开始节点都是相同的,所以,最后一次相同的节点,就是距离他们最近的公共节点。
思想
活用Hash表:
如果每个节点有指向父节点的指针,那么逆向遍历两个节点的所有祖先节点,找第一个一样的祖先,可用hash表存储,
时间复杂度是树的深度,空间复杂度也是数的深度。
可以将q到头结点建立一张Hash表,然后从p到头结点,边遍历边查找Hash表,直到第一次在hash表在哦个查找到节点值存在。
(其实我们可以简单的过程来看思想二的算法:我们可以开辟指向节点的指针数组,先从一个节点下手,让它一直回退,每退一步,数组新的位置记录下它,即指向该节点,直到第一个节点回退完,再进行第二个节点的回退,每退一步就检查一下它在数组中有没有,这样和思想一是一样的,故为了加速,这里应该将每一个节点的回退过程的地址扔进hashset里去,在回退第二个节点时,查一下hashset里有没有此节点,有则找到所以的祖先节点,没有就继续找)
相关文章推荐
- 总结
- JavaSE随笔——原码反码补码
- 模拟退火算法
- aX+bY+cZ=n(非负整数解存在性)
- 深入理解php-fpm.conf中的max_children和request_terminate_timeout
- Navicat 怎么生成ER图表
- Minor【 PHP框架】2.第一个应用与请求的生命周期
- 最短路径(Shortest Path)
- HDU1078FatMouse and Cheese
- android四大组件--ContentProvider
- Selenium Webdriver
- duplicate symbol _OBJC_CLASS 错误处理方法
- 一文搞懂HMM(隐马尔可夫模型)
- 2016年06月15日学习日记 c++第一讲
- Android-x86 5.1系统源码重定制开发----------开篇《阐明》
- Android实现天气预报(中国天气网)
- 领导的素养
- 【MyBatis学习12】MyBatis中的一级缓存
- 空操作命名空间
- Android中Service(服务)详解