求一颗不含指向父节点指针的普通树中任意两个结点的最近公共祖先(O(N*N) 和 O(N) 算法)
2017-06-29 15:51
369 查看
//方法1 来自剑指offer //#include <iostream> //#include <list> //#include <vector> //using namespace std; //#include "BinaryTree.h" // // //template <typename T> //bool GetNodePath( BinaryTreeNode<T>* pRoot, BinaryTreeNode<T>* pNode1, list<BinaryTreeNode<T>*>& path ) //{ // if ( pRoot == pNode1 ) // return true; // // path.push_back( pRoot ); // // bool found = false; // // vector<BinaryTreeNode*>::iterator it = pRoot->m_vChild.begin( ); // // while ( (false == !found) && (i < pRoot->m_vChild.end( )) ) // { // found = GetNodePath( *i, pNode, path ); // ++i; // } // // if ( true == !found ) // path.pop_back( ); // // return found; //} // //template<typename T> //BinaryTreeNode<T>* GetLastCommonNode( const list<BinaryTreeNode<T>*>& path1, const list<BinaryTreeNode<T>*>& path2 ) //{ // list<BinaryTreeNode<T>*>::const_iterator iterator1 = path1.begin( ); // list<BinaryTreeNode<T>*>::const_iterator iterator2 = path2.begin( ); // // BinaryTreeNode<T>* pLast = NULL; // // while ( iterator1 != path1.end( ) && iterator2 != path2.end( ) ) // { // if ( *iterator1 == *iterator2 ) // *pLast = *iterator1; // // iterator1++: // iterator2++: // } // // return pLast; //} // //template <typename T> ////BinaryTreeNode<T>/*这还是要写 T 的呀, 不是上面写了 template 这就不用写了, 上面写, 是说 这是一个模板函数 会用到类型T,所以下面哪里用到类型T,当然是要说明的. 比如, BinaryTreeNode<T>这里用到了 */ //BinaryTreeNode<T>* GetLastCommonParent( BinaryTreeNode<T>* pRoot, BinaryTreeNode<T>* pNode1, BinaryTreeNode<T>* pNode2 ) //{ // if ( NULL == pRoot || NULL == pNode1 || NULL == pNode2 ) // return NULL; // // list<BinaryTreeNode<T>*> path1; // GetNodePath( pRoot, pNode1, path1 ); // // list<BinaryTreeNode<T>*> path2; // GetNodePath( pRoot, pNode2, path2 ); // // return GetLastCommonParent( path1, path2 ); //} #pragma once struct BinaryTreeNode { char _data; BinaryTreeNode* _left; BinaryTreeNode* _right; BinaryTreeNode( char x ) : _data( x ) , _left( NULL ) , _right( NULL ) {} }; typedef BinaryTreeNode Node; class BinaryTree { public://因为我们没有私有成员变量, 所以都不需要构造函数 Node* _root; Node* CreateTree( char*& a ) { Node* root = NULL; if ( '\0' != *a && '#' != *a ) { root = new Node( *a ); root->_left = CreateTree( ++a ); root->_right = CreateTree( ++a ); } return root; } //时间复杂度 O(N*N) 方法2 Node* GetCommonAncestor( Node* root, char x1, char x2 ) { if ( NULL == root ) return NULL; //1. x1 / x2 等于 root if ( root->_data == x1 || root->_data == x2 ) return root; //2. bool x1InLeft; //注意 Node* x1InLeft, x2InRight 是 定义了 一个Node* 的x1InLft 和 一个Node的 x2InRight 别犯错! bool x1InRight; bool x2InLeft; bool x2InRight; x1InLeft = Find( root->_left, x1 ); x1InRight = Find( root->_right, x1 ); x2InLeft = Find( root->_left, x2 ); x2InRight = Find( root->_right, x2 ); if ( x1InLeft && x2InRight || x1InRight && x2InLeft ) return root; else if ( x1InLeft && x2InLeft ) return GetCommonAncestor( root->_left, x1, x2 ); else if ( x1InRight && x2InRight ) return GetCommonAncestor( root->_right, x1, x2 ); else//两个结点中 至少有一个不在这棵树中. assert( false ); } bool Find( Node* root, char x ) { if ( NULL == root ) return false; if ( root->_data == x ) return true; bool ret = Find( root->_left, x ); if ( true == ret ) return true; return Find( root->_right, x ); } //方法1 的另一种写法 //找到两条结点的路径后. 先从栈中把数据多的那条路经pop, 直到两者元素数量相同. 再找它们最后一个公共结点. bool GetPath( Node* root, char x, stack<Node*>& paths ) { if ( NULL == root ) return false; paths.push( root ); if ( x == root->_data ) return true; if ( true == GetPath( root->_left, x, paths ) ) return true; if ( true == GetPath( root->_right, x, paths ) ) return true; paths.pop( ); return false; } }; void TestTree( ) { char* a1 = "123##4##56###"; BinaryTree t1; Node* root1 = t1.CreateTree( a1 ); } int main( ) { TestTree( ); return 0; }
.h:
#ifndef BINARY_TREE_H_ #define BINARY_TREE_H_ template<class T> struct BinaryTreeNode { BinaryTreeNode<T>* _left; BinaryTreeNode<T>* _right; T _date; BinaryTreeNode( const T& x ) :_date( x ) ,_left( NULL ) ,_right( NULL ) {} }; template<class T> class BinaryTree { typedef BinaryTreeNode<T> Node; public: BinaryTree( ) :_root( NULL ) {} BinaryTree( T* a, size_t n, const T& invalid = T( ) ) { size_t index = 0; _root = CreateTree( a, n, invalid, index ); } Node* Find( const T& x ) { return _Find( _root, x ); } protected: Node* _root; Node* CreateTree( T* a, size_t n, const T& invalid, size_t& index )//因为递归会创建多个index变量,为使index值正确,此处用引用 而第一处用引用是处于节省空间考虑 { Node* root = NULL; //采用前序遍历创建二叉树 if ( (index < n) && (a[index] != invalid) )//先序前序后序是以根为前中后. 通过数组写树时, 按顺序写 比如前序 根左右 就先写大框架,留出缝隙, 在当子问题处理, 往中间加数据(即把根 左 右都当作一个新根 子问题) { root = new Node( a[index] ); //注意圆括号与方括号的区别 圆括号构建一个用delete 而方括号构建多个 用delete[] root->_left = CreateTree( a, n, invalid, ++index );//构建完左子树再执行下面构建右子树 root->_right = CreateTree( a, n, invalid, ++index ); } return root; } Node* _Find( Node* root, const T& x ) { if ( NULL == root ) { return NULL; } if ( x == root-> _date ) { return root; } Node* ret; //声明与定义分离 ret = _Find( root->_left, x ); if ( NULL != ret ) //只需写一个条件, ret 不为NULL 即找到了 //递归每层都是返回到哪一句呢? 递归的那一句 { return ret; } return ( _Find( root->_right, x ) ); //不用像上面一样写个条件判断,直接return 未找到即返回NULL,否则即找到了 } }; #endif
相关文章推荐
- 一颗普通的二叉树,如何寻找两个节点的最低公共祖先(发现的一个与算法无关的引用问题)
- 在二叉树中,求任意两个节点的最近公共祖先(遍历的应用算法)
- 二叉树中任意两个节点的最近公共祖先节点
- 利用栈结构实现二叉树的非递归遍历,求二叉树深度、叶子节点数、两个结点的最近公共祖先及二叉树结点的最大距离
- 利用栈结构实现二叉树的非递归遍历,求二叉树深度、叶子节点数、两个结点的最近公共祖先及二叉树结点的最大距离
- 求二叉树中两个节点的最近公共祖先(三叉链,搜索树,普通二叉树)
- 求二叉树的任意两个节点的最近公共祖先
- 二叉树的最近公共祖先、两个最远节点、第K层结点个数、出现次数超过一半的元素
- LCA算法求任意两个节点之间的最小公共祖先(最短路径)
- 求二叉树中两个节点的最近公共祖先结点
- 利用栈结构实现二叉树的非递归遍历,求二叉树深度、叶子节点数、两个结点的最近公共祖先及二叉树结点的最大距离
- LCA问题:求二叉树中任意两个节点的最近公共祖先
- 在二叉树中查找两个节点的最近的公共祖先节点(无回溯指针)(NCA--nearest common ancestor)
- 后序遍历非递归求结点的所有祖先(或求两个节点的最近公共祖先)
- 通过邻接矩阵找到两个节点的最近公共祖先结点
- 设计算法查找二叉树的两个结点最近公共祖先(LCA)
- 在二叉树中查找两个节点的最近的公共祖先节点(有回溯指针)(NCA--nearest common ancestor)
- 【算法面试题】寻找二叉搜索树中两个节点的最近公共祖先节点(转)
- [算法 笔记] 查找二叉树上任意两个结点的最近共同祖先(更新版本)
- 面试算法(五十)树中两个结点的最低公共祖先