您的位置:首页 > 职场人生

求一颗不含指向父节点指针的普通树中任意两个结点的最近公共祖先(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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  面试题
相关文章推荐