Find Common Ancestor

来源:互联网 发布:有哪些好听的网络歌曲 编辑:程序博客网 时间:2024/05/29 14:40

Problem: find the common ancestor of two nodes in a tree

Given a "tree" pointer pointing to the root node of a tree and the other two pointers to two nodes in the tree. You are expected to write a C++ subroutine to find the common ancestor of the two nodes. In any unexpected condition, your code should return null pointer and avoid crashing.

For example, if the tree is like below, B is the common ancestor of E and G; A is the common ancestor of H and F; D is the common ancestor of D and G.

You are allowed to use recursion but as few as possible. You are NOT allowed to use STL. Please follow the type definitions shown below:

//tree node type
typedef struct _Node{ char value; struct _Node* left; struct _Node* right;}Node;class CommonNodeFinder{ //add any auxiliary code here as you wish.public: inline Node* FindCommonAncestor(Node* tree, Node* node_1, Node* node_2) { //your code here. }}
my solution:

#include <iostream>

template< typename T >

class stack{ 

public:

       struct Node{

              T value;

              Node* next;

       };

public:

       stack()

       {

              phead = NULL;

       }

       virtual ~stack()

       {

              Node* pnode = phead;

              while ( pnode != NULL )

              {

                     phead = phead->next;

                     delete pnode;

                     pnode = phead;

              }           

       }

       void push_back( T value )

       {

              Node* ptempnode = new Node;

              ptempnode->value = value;

              ptempnode->next = phead;

              phead = ptempnode;

       }

       T get( ) const

       {

              return phead->value;

       }

       void pop_up( )

       {

              Node* pnode;

              pnode = phead;  

              phead = phead->next;

              delete pnode;

       }

       bool is_empty( ) const

       {

              if ( phead == NULL )

                     return true;

              else

                     return false;

       }

 

private:

       Node* phead;

};

 

template < typename T >

struct Node

{

       T value;

       Node* left;

       Node* right;

};

 

void visit( Node<char>* p )

{

       std::cout << p->value << std::endl;

}

class CommonNodeFinder

{

public:

       // auxiliary function used for generating tree

       void generate_tree( char tree_serial[] )

       {

              int n = strlen( tree_serial );

              if ( n < 1 )

              {

                     tree_phead = NULL;

                     return;

              }

              Node<char>* node;

              node = new Node<char>;

              node->value = tree_serial[0];

              node->left = generate_child( tree_serial, 1, n );

              node->right = generate_child( tree_serial, 2, n );

              tree_phead = node;

              return;

       }

       // auxiliary function used for generating tree

       Node<char>* generate_child( char tree_serial[], const int& index, const int& length )

       {

              if ( index >= length || tree_serial[index] == ' ' )

                     return NULL;

              Node<char>* node;

              node = new Node<char>;

              node->value = tree_serial[index];

              node->left = generate_child( tree_serial, 2 * index + 1 , length );

              node->right = generate_child( tree_serial, 2 * index + 2, length );

              return node;

       }

       // auxiliary function used for visit the tree

       void pre_order_traverse( Node<char>* pnode, void ( *visit ) ( Node<char>* p ))

       {

              if( pnode != NULL )

              {

                     visit( pnode );

                     pre_order_traverse( pnode->left, visit );

                     pre_order_traverse( pnode->right, visit );

              }

       }

 

       // auxiliary function used for delete the tree

       void delete_tree( Node<char>* pnode )

       {

              if ( pnode != NULL )

              {

                     delete_tree( pnode->left );

                     delete_tree( pnode->right );

                     delete pnode;

              }

       }

       // get the Node by the value

       Node<char>* find_in( char val, Node<char>* root )

       {

              Node<char>* node;

              if( root == NULL )

                     return NULL;

              else if ( root->value == val )

                     return root;

              else if ( ( node = find_in( val, root->left ) ) != NULL )

                     return node;

              else if ( ( node = find_in( val, root->right ) ) != NULL )

                     return node;

              else

                     return NULL;

       }

       //generator the ancestor stack for node in the root

       bool is_belong_to( Node<char>* node, Node<char>* root, stack< Node<char>* >& ancestors )

       {

              if ( root == NULL )

                     return false;

              else if ( node == root )

              {

                     ancestors.push_back( root );

                     return true;

              }

              else if ( is_belong_to( node, root->left, ancestors ) )

              {

                     ancestors.push_back( root );

                     return true;

              }

              else if ( is_belong_to( node, root->right, ancestors ) )

              {

                     ancestors.push_back( root );

                     return true;

              }

              else

                     return false;

       }

 

public:

       Node<char>* tree_phead;

       CommonNodeFinder( )

       {

              tree_phead = NULL;

       }

       virtual ~CommonNodeFinder( )

       {

              delete_tree( tree_phead );

       }

public:

       inline Node<char>* FindCommonAncestor(Node<char>* tree, Node<char>* node_1, Node<char>* node_2)

       {

              stack< Node<char>* > ancestor1;

              stack< Node<char>* > ancestor2;

              is_belong_to( node_1, tree, ancestor1 );

              is_belong_to( node_2, tree, ancestor2 );

              if ( ancestor1.is_empty() )

                     return NULL;

              if ( ancestor2.is_empty() )

                     return NULL;

              Node<char> *a1, *a2, *a;

              a1 = ancestor1.get();

              a2 = ancestor2.get();

              while ( a1 == a2 )

              {

                     a = a1;

                     ancestor1.pop_up();

                     if ( ancestor1.is_empty() )

                            break;

                     ancestor2.pop_up();

                     if ( ancestor2.is_empty() )

                            break;

                     a1 = ancestor1.get();

                     a2 = ancestor2.get();

              }

              return a;

       }

};

// test code

int main ( int argc, char* argv[] )

{

       CommonNodeFinder NodeFinder;

       Node<char>* node1;

       Node<char>* node2;

       Node<char>* node;

 

       NodeFinder.generate_tree( "ABCDE HFG" );

       node1 = NodeFinder.find_in( 'D', NodeFinder.tree_phead );

       node2 = NodeFinder.find_in( 'G', NodeFinder.tree_phead );

       node = NodeFinder.FindCommonAncestor( node1, NodeFinder.tree_phead, node2 );

       if ( node )

              std::cout << node->value << std::endl;

}