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