#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
Binary search tree
最新推荐文章于 2022-08-07 11:30:59 发布