1. 程式人生 > >【資料結構】二叉樹中任意兩節點的最近公共祖先節點

【資料結構】二叉樹中任意兩節點的最近公共祖先節點

問題要求:任意給出二叉樹中的兩個節點,求他們的最近祖先

分三種情況:

1、該二叉樹是搜尋二叉樹

如果兩個節點的值都大於根節點,則遍歷右子樹查詢一個處於兩節點之間的值為最近祖先,如果兩個節點的值都小於根節點,則遍歷左子樹查詢一個兩節點之間的值為最近祖先

插入程式碼

Node* SearchNearAncestor(Node* root,Node* node1,Node*node2)
	{
		if (root==NULL||
			node1==NULL||
			node2==NULL)
		{
			return NULL;
		}
		if(node1==node2||node1->_parent!=NULL)
		{
			return node1;
		}
		Node* cur=root;
		while (cur)
		{
			if(cur->_key>node1->_key&&
				cur->_key>node2->_key)
			{
              cur=cur->_left;
			}
			else if(cur->_key<node1->_key&&
				cur->_key<node2->_key)
			{
				cur=cur->_right;
			}
			else 
			{
				if(node1->_parent==node2)
					return node2->_parent;
				else if(node2->_parent==node1)
					return node1->_parent;
				else
				return cur;
			}
		}

		return NULL;
	}
2、該二叉樹為普通二叉樹,但其有父節點,這時候,將node1的父節點和node2的parent->parent.......一直比較下去,直到二者相同,如果一直不同,則將node1再往上走,繼續上步迴圈

查詢程式碼為

Node* NearAncetor(Node* root,Node* node1,Node* node2)
	{
		if(node1==root||node2==root)
		{
			return root;
		}
		Node* tmp;
		while (node1!=NULL)
		{
			node1=node1->_parent;
			tmp=node2;
			while (tmp!=NULL)
			{
				if(node1==tmp->_parent)
					return node1;

				tmp=tmp->_parent;
			}
		}
		return NULL ;
	}

3、該二叉樹為普通二叉樹,他也沒有父節點,這時候要分別遞迴左右子樹,如果一個節點出現在左子樹,另一個出現在右子樹,則返回根節點,如果兩個都出現在左,則最近祖先在子樹,如果兩個都出現在右,則最近祖先在右子樹上

程式碼如下

Node* NearAncetor(Node* root,Node* node1,Node* node2)
	{
		if (root==NULL||
			node1==NULL||
			node2==NULL)
		{
			return NULL;
		}
		if(node1==root||node2==root)
		{
			return root;
		}
		Node* left=NearAncetor(root->_left,node1,node2);
		Node* right=NearAncetor(root->_right,node1,node2);
		if(left&&right)
			return root;
		if(left==NULL)
			return right;
		else
			return left;
	}

二叉搜尋樹全部程式碼
#include<iostream>
using namespace std;
template<class K>
struct SearchTreeNode 
{
	typedef SearchTreeNode<K> Node;
	Node* _left;
	Node* _right;
	Node* _parent;
	K _key;
	SearchTreeNode(const K& key)
		:_left(NULL)
		,_right(NULL)
		,_parent(NULL)
		,_key(key)
	{}
};
template<class K>
class SearchTree
{
	typedef SearchTreeNode<K> Node;
public:
	SearchTree()
	:_root(NULL)
	{}
	~SearchTree()
	{
		delete _root;
	}
	SearchTree(const SearchTree<K>& t)  
	{  
		_root=t._root;  
	}  
	Node* GetRoot()
	{
		return _root;
	}
	bool Find(const K& key)
	{
		if(_root==NULL)
			return false;
		Node* cur=_root;
		while (cur)
		{
			if(cur->_key>key)
				cur=cur->_left;
			else if(cur->_key<key)
				cur=cur->_right;
			else 
				return true;
		}
	}
	bool Insert(const K&key)
	{
		_Insert(_root,key);
		return true;
	}
	void Inorder()
	{
		_Inorder(_root);
		cout<<endl;
	}
	Node* SearchNearAncestor(Node* root,Node* node1,Node*node2)
	{
		if (root==NULL||
			node1==NULL||
			node2==NULL)
		{
			return NULL;
		}
		if(node1==node2||node1->_parent!=NULL)
		{
			return node1;
		}
		Node* cur=root;
		while (cur)
		{
			if(cur->_key>node1->_key&&
				cur->_key>node2->_key)
			{
              cur=cur->_left;
			}
			else if(cur->_key<node1->_key&&
				cur->_key<node2->_key)
			{
				cur=cur->_right;
			}
			else 
			{
				if(node1->_parent==node2)
					return node2->_parent;
				else if(node2->_parent==node1)
					return node1->_parent;
				else
				return cur;
			}
		}

		return NULL;
	}
protected:
	
	bool _Insert(Node*& root, const K& key)
	{
		if(root==NULL)
		{
		  root=new Node(key);
		  return true;
		}
		if(root->_key>key)
		{
			return _Insert(root->_left,key);
		}
		else if(root->_key<key)
		{
			return _Insert(root->_right,key);
		}
		else
			return false;
	}
	void _Inorder(Node* root)
	{
		Node* cur=root;
		if(cur==NULL)
			return;
		_Inorder(cur->_left);
		cout<<cur->_key<<" ";
		_Inorder(cur->_right);
	}
protected:
	Node* _root;
};
//void testSearch()
//{
//	int arr[]={3,4,1,5,2,6,8,7,9};
//	SearchTree<int> t;
//	
//	
//	for(int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
//	{
//		t.Insert(arr[i]);
//	}
//	t.Inorder();
//  
//}
void test()
{
	int arr[]={5,3,4,1,7,8,2,6,0,9};
	SearchTree<int> t1;
	for(int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
	{
		t1.Insert(arr[i]);
	}
	t1.Inorder();
	SearchTreeNode<int>* root=t1.GetRoot();
	SearchTreeNode<int>* node1=root->_left->_right;
	SearchTreeNode<int>* node2=root->_right->_left;
	SearchTreeNode<int>* ancetor=t1.SearchNearAncestor(root,node1,node2);
	cout<<node1->_key<<"和"<<node2->_key<<"的最近祖先是"<<ancetor->_key<<endl;
	SearchTreeNode<int>* node3=root->_right->_right->_right;
	SearchTreeNode<int>* node4=root->_right->_left;
	SearchTreeNode<int>* ancetor2=t1.SearchNearAncestor(root,node3,node4);
	cout<<node3->_key<<"和"<<node4->_key<<"的最近祖先是"<<ancetor2->_key<<endl;
	cout<<endl;
}

這裡查詢4,6的最近祖先和9,6的最近祖先

結果

普通二叉樹有父節點的全部程式碼

#include <iostream>
using namespace std;
struct TreeNode
{
	TreeNode* _left;
	TreeNode* _right;
	TreeNode* _parent;
	int _key;
	TreeNode(const int& key)
		:_left(NULL)
		,_right(NULL)
		,_parent(NULL)
		,_key(key)
	{}
};
class BinrayTree
{
	typedef TreeNode Node;
public:
    BinrayTree()
		:_root(NULL)
	{}
	~BinrayTree()
	{
		delete _root;
	}
	Node* GetRoot()
	{
		return _root;
	}
	bool Insert2(const int& key)
	{
		_Insert(_root,key);
		return true;
	}
	void Inorder2()
	{
		_Inorder(_root);
		cout<<endl;
	}
	Node* NearAncetor(Node* root,Node* node1,Node* node2)
	{
		if(node1==root||node2==root)
		{
			return root;
		}
		Node* tmp;
		while (node1!=NULL)
		{
			node1=node1->_parent;
			tmp=node2;
			while (tmp!=NULL)
			{
				if(node1==tmp->_parent)
					return node1;

				tmp=tmp->_parent;
			}
		}
		return NULL ;
	}
protected:
	bool _Insert(Node*& root,const int& key)
	{
		Node* node=new Node(key);
		node->_key=key;
		node->_left=node->_right=node->_parent=NULL;
		if(root==NULL)
		{
			root=node;
			return true;
		}
		if(root->_left == NULL && root->_key > key)
		{
			node->_parent=root;
			root->_left=node;
			return true;
		}
		if(root->_right == NULL && root->_key < key)
		{
			node->_parent=root;
			root->_right=node;
			return true;
		}
		if(root->_key > key)
			_Insert(root->_left,key);
		else if(root->_key < key)
			_Insert(root->_right,key);
		else
			return true;
	}
	void  _Inorder(Node* root)
	{
		Node* cur=root;
		if(cur==NULL)
			return;
		_Inorder(cur->_left);
		cout<<cur->_key<<" ";
		_Inorder(cur->_right);
	}
	Node* _root;
};
void test2()
{
	int arr[]={5,3,4,1,7,8,2,6,0,9};
	BinrayTree t1;
	for(int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
	{
		t1.Insert2(arr[i]);
	}
	t1.Inorder2();
	TreeNode* root=t1.GetRoot();
	TreeNode* node1=root->_left->_left;
	TreeNode* node2=root->_right->_right;
	cout<<node1->_key<<"和"<<node2->_key<<"的最近祖先是";
	TreeNode* ancetor=t1.NearAncetor(root,node1,node2);
	if(ancetor)
	cout<<ancetor->_key<<endl;
	cout<<endl;
}


這裡測試1,8的最近祖先

普通二叉樹且無父節點全部程式碼

#include <iostream>
using namespace std;
struct NoParentTreeNode
{
	NoParentTreeNode* _left;
	NoParentTreeNode* _right;
	int _key;
	NoParentTreeNode(const int& key)
		:_left(NULL)
		,_right(NULL)
		,_key(key)
	{}
};
class NoParentBinrayTree
{
	typedef NoParentTreeNode Node;
public:
	NoParentBinrayTree()
		:_root(NULL)
	{}
	~NoParentBinrayTree()
	{
		delete _root;
	}
	Node* GetRoot()
	{
		return _root;
	}
	bool Insert2(const int& key)
	{
		_Insert(_root,key);
		return true;
	}
	void Inorder2()
	{
		_Inorder(_root);
		cout<<endl;
	}
	Node* NearAncetor(Node* root,Node* node1,Node* node2)
	{
		if (root==NULL||
			node1==NULL||
			node2==NULL)
		{
			return NULL;
		}
		if(node1==root||node2==root)
		{
			return root;
		}
		Node* left=NearAncetor(root->_left,node1,node2);
		Node* right=NearAncetor(root->_right,node1,node2);
		if(left&&right)
			return root;
		if(left==NULL)
			return right;
		else
			return left;
	}
protected:
	bool _Insert(Node*& root,const int& key)
	{
		if(root==NULL)
		{
			root=new Node(key);
			return true;
		}
		if(key>root->_key)
		{
			return  _Insert(root->_right,key);
		}
		else if(key<root->_key)
		{
			return  _Insert(root->_left,key);
		}
		else 
			return false;
	}
	void  _Inorder(Node* root)
	{
		Node* cur=root;
		if(cur==NULL)
			return;
		_Inorder(cur->_left);
		cout<<cur->_key<<" ";
		_Inorder(cur->_right);
	}
	Node* _root;
};
void test3()
{
	int arr[]={5,3,4,1,7,8,2,6,0,9};
	NoParentBinrayTree t1;
	for(int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
	{
		t1.Insert2(arr[i]);
	}
	t1.Inorder2();
	NoParentTreeNode* root=t1.GetRoot();
	NoParentTreeNode* node1=root->_left->_left;
	NoParentTreeNode* node2=root->_right->_right->_right;
	NoParentTreeNode* ancetor=t1.NearAncetor(root,node1,node2);
	cout<<node1->_key<<"和"<<node2->_key<<"的最近祖先是"<<ancetor->_key<<endl;
	cout<<endl;
}

這裡測試1,9的最近祖先


測試程式碼

#include "SearchTree.h"
#include "HaveParentUnsearchTree.h"
#include "NoParentSearchTree.h"
#include <cstdlib>
int main()
{
	test();
	test2();
	test3();
	system("pause");
	return 0;
}