Binary search tree

#include <iostream>
#include <vector>

using std::cin;
using std::cout;
using std::endl;
using std::vector;

template<class Type>
struct BinaryNode
{
	Type num;
	struct BinaryNode *llink;
	struct BinaryNode *rlink;
	typedef BinaryNode<Type> Node;
};//Node;

template <class Type>
class BinaryTree
{
	typedef BinaryNode<Type> Node;
	private:		
		Node *root;		
		Node *child;
	public:
		BinaryTree();										// 建構子
		~BinaryTree();										// 解構子
		void buildBinaryTree( vector<Type> &v );			// 從容器建立 BinaryTree
		Node *findParent( Type input , Node *parent );		// 取得內函input的結點的父結點
		void inorder( Node *node );							// 中序拜訪以node為樹根的子樹
		Node *getRoot()const{ return root ;}				// 取得root
		int nodeCount( Node *root) const;					// 計算數的總結點數目
		void release(Node *parent);							// 釋放整顆樹的記憶體空間
		Node *getNode(Node *root, Type target);				// 取得內含某個特定值的Node Pointer
		Node *minKth(Node *root, int k ) const;				// 尋找第k小的成員
		Node *maxKth(Node *root, int k ) const;				// 尋找第k大的成員
};//end of class BinaryTree


template <class Type>
BinaryTree<Type>::BinaryTree()
	:root(NULL), child(NULL)			// 初始化root 和 child 指標指向 NULL,
{

}//end of ctor

template <class Type>
BinaryTree<Type>::~BinaryTree()	
{
	release(root);
}//end of dtor


template <class Type>
void BinaryTree<Type>::release( Node *parent)	
{
	// 採 左右中postOrder的方式清除記憶體
	if( parent == NULL ) return;
	
	release( parent->llink);
	release( parent->rlink);
	delete parent;
}//end of release

template <class Type>
void BinaryTree<Type>::buildBinaryTree(  vector<Type> &v)
{
	if( v.size() == 0 )
	{
		cout << " Empty tree" ;
		return;
	}
	
	// 建立樹根
	root =(Node*) new Node;
	root -> num  = (Type)*v.begin();
	root -> llink = NULL;
	root -> rlink = NULL;

	// 建立子樹(子結點)
	child =(Node*) new Node;
	// 從vector第二個元素開始,因為第一個元素已經拿去建立root了
	for( typename vector<Type>::iterator it = v.begin()+1 ; it != v.end() ; ++it )
	{
		child->num = (Type)(*it);
		child->llink = NULL;
		child->rlink = NULL;
		// 尋找新結點insert位置的父結點
		Node *newNodeParent = findParent( child->num , root );

		// 假如子結點的數值 比 父結點 大,則放在父結點的右連結
		if( child->num  >  newNodeParent->num )
		{
			newNodeParent->rlink = child;
		}
		// 假如子結點的數值 比 父結點 小,則放在父結點的左連結
		else
		{
			newNodeParent->llink = child;		
		}

		//為下一個結點分配記憶體空間
		child = (Node *)new Node;
	}//end of loop

	return ;
}//end of template member function buildBinaryTree

template <class Type>
typename BinaryTree<Type>::Node *BinaryTree<Type>::minKth(typename BinaryTree<Type>::Node *root, int k ) const
{
	if( root == NULL )
		return NULL;
	int leftNodeCount = nodeCount( root->llink );		// 計算左子樹總結點
	
	if( k == leftNodeCount +1 )							// 左子樹的總點數恰有k-1個,root 剛好是第k 小
		return root;
	else if( leftNodeCount < k)							// 左子樹的總點數不足k個,將往右子樹搜尋
		return minKth( root->rlink, k-leftNodeCount-1 );// kth 扣掉 左子樹總點數 再 扣掉 root
	else
		return minKth( root->llink, k);					// 左子樹的總點數大於等於k個,將往左子樹搜尋第k小
	
}//end of template member function minKth


template <class Type>
typename BinaryTree<Type>::Node *BinaryTree<Type>::maxKth(typename BinaryTree<Type>::Node *root, int k ) const
{
	if( root == NULL )
		return NULL;
	int rightNodeCount = nodeCount( root->rlink );		// 計算右子樹總結點
	
	if( k == rightNodeCount +1 )						// 右子樹的總點數恰有k-1個,root 剛好是第k 大
		return root;
	else if( rightNodeCount < k)						// 右子樹的總點數不足k個,將往左子樹搜尋
		return maxKth( root->llink, k-rightNodeCount-1 );// kth 扣掉 右子樹總點數 再 扣掉 root
	else
		return maxKth( root->rlink, k);					// 右子樹的總點數大於等於k個,將往右子樹搜尋第k大
	
}//end of template member function maxKth



template <class Type>
typename BinaryTree<Type>::Node *BinaryTree<Type>::getNode(typename BinaryTree<Type>::Node *root, Type target)
{
	Node *iter = root;
	while(iter != NULL)
	{
		if( iter->num == target)
			break;
		else if( target > iter->num )
			iter = iter->rlink;
		else
			iter = iter->llink;
	}
	return iter;
}//end of template member function getNode

template <class Type>
typename BinaryTree<Type>::Node *BinaryTree<Type>::findParent( Type input , typename BinaryTree<Type>::Node *parent )
{
	// 第一種版本
	// old version
	//if( input > parent->num && parent->rlink != NULL )
	//{
	//	findParent( input , parent->rlink );
	//}
	//else if( input < parent->num && parent->llink != NULL ) 
	//{	findParent( input , parent->llink );
	//}
	//else
	//{	return parent;
	//}
	//

	// 第二種版本 插入新結點 和 搜尋舊有結點都通用

	Node *prev = NULL;								// 紀錄父結點的trick
	while( parent != NULL && parent->num != input )
	{
		
		prev = parent ;
		if( input > parent->num )
			parent = parent->rlink;
		else
			parent = parent->llink;
		
	}//end of while parent != NULL
	return prev;
}//end of template member function findParent

template <class Type>
void BinaryTree<Type>::inorder( Node *node )
{
	if( node != NULL )
	{
		// 左子樹 -> 樹根 -> 右子樹順序拜訪
		inorder( node -> llink );
		cout << node -> num << "  " ;
		inorder( node -> rlink );
	}

}//end of template member function inorder

template <class Type>
int BinaryTree<Type>::nodeCount( Node *root) const
{
	if( root == NULL )				// root 為空
		return 0 ;
	else                            // root 不為空
		if( root->llink == NULL && root->rlink == NULL )	// root 左右子結點皆為空,回傳1
			return 1;
		else
			return 1 + nodeCount( root->llink ) + nodeCount( root->rlink );		// root 左右子結點有一不為空,回傳 1 + 左子結點總數 + 右子結點總數
}//end of nodeCount

template <class Type>
void getInput(vector<Type> &v);							// 從cin取得鍵盤輸入
template <class Type>
void findParentTest(const BinaryTree<Type> &t);			// findParent function test
template <class Type>
void minKthTest(const BinaryTree<Type> &t);				// 找第k小的結點 function test
template <class Type>
void maxKthTest(const BinaryTree<Type> &t);				// 找第k大的結點 function test

int main( int argc, char* argv[] )
{
	BinaryTree<int> obj;

	vector<int> vec;

	getInput(vec);						// 從 cin 取得輸入

	obj.buildBinaryTree( vec );			// 建立 BinaryTree

	obj.inorder( obj.getRoot() );		// 中序inOrder 拜訪整個BST

	minKthTest(obj);
	//functionTest(obj);

	system("pause");
	return EXIT_SUCCESS;
}//end of main

template <class Type>
void minKthTest(const BinaryTree<Type> &t)
{
	int total = t.nodeCount(t.getRoot() );
	
	if( total == 0 ) 
		return;				// 整顆樹沒有結點,直接return
	
	const BinaryNode<Type> *node;
	cout <<endl;
	for(int i = 1 ; i <= total ; ++i )
	{
		node = t.minKth(t.getRoot(),i);
		if( node == NULL )
			break;
		cout <<"第 "<< i << " 小 : " << node->num << endl;
	}//end of for
	return;
}//end of minKthTest

/*
不能在識別項中使用這個字元

解答:全形空白造成的。
*/


template <class Type>
void maxKthTest(const BinaryTree<Type> &t)
{
	int total = t.nodeCount(t.getRoot() );
	if( total == 0 ) 
		return;				// 整顆樹沒有結點,直接return
	const BinaryNode<Type> *node;
	cout <<endl;
	for(int i = 1 ; i <= total ; ++i )
	{
		node = t.maxKth(t.getRoot(),i);
		if( node == NULL )
			break;
		cout <<"第 "<< i << " 大 : " << node->num << endl;
	}//end of for
	return;
}//end of minKthTest

template <class Type>
void getInput( vector<Type> &v)
{
	// 輸入 數個integer 給 vec
	Type temp(-2);
	cout << "輸入數個數字,-1結尾。" << endl;
	while( cin >> temp )
	{
		if( static_cast<int>(temp) == -1)
		{ break; }

		v.push_back( temp );		
	}//end of while loop
}//end of global function getInput



template <class Type>
void findParentTest( BinaryTree<Type> &obj)
{
	//
	// 測式輸入資料 5 8 7 6 2 4 3 1 9 10 -1
	// 答案 4 2
	BinaryNode<int> *ptr= obj.getNode(obj.getRoot(),4);
	if( ptr!= NULL )
	{
		cout << endl << " Target : " << ptr->num << endl;
		cout <<" Target's parent : " << obj.findParent( 4, obj.getRoot() )->num << endl;
	}


	//cout << obj.nodeCount( obj.getRoot() );
	return;
}//end of global function functionTest

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值