//方法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