二叉搜索树定义
1.每个结点都有一个作为搜索依据的关键码,所有结点的关键码都不相同。
2.左子树上所有结点的关键码都小于根节点的关键码。
3.右子树上所有结点的关键码都大于根节点的关键码。
4.左子树和右子树也是二叉搜索树。
二叉搜索树实现
使用c++实现二叉搜索树,这些是必要的声明。
#include <iostream>
#include <stack>
using namespace std;
template <class Type> class BST; //二叉搜索树的前向声明
首先给出二叉搜索树的结点数据结构,和普通树的结点类相同。
template <class Type>
class BstNode
{
template <class T>
friend class BST; //BST需要访问私有成员data
public:
//构造函数
BstNode() : leftChild( NULL ), rightChild( NULL ) {}
BstNode( const Type d = 0, BstNode* L = NULL, BstNode* R = NULL )
: data( d ), leftChild( L ), rightChild( R ) {}
~BstNode() {}
//Type get_data() { return data; }//测试中用到
protected:
Type data; //结点数据域
BstNode<Type>* leftChild, *rightChild;
};
二叉搜索树的抽象数据类型。
template <class Type>
class BST
{
public:
BST() : root( NULL ) {}
BST( Type value ); //指定输入结束符的构造函数
~BST() { MakeEmpty( root ); }
void MakeEmpty() { MakeEmpty( root ); root = NULL; }
void PrintTree() { PrintTree( root ); }
int Find( const Type&x ) const { return Find( x, root ) != NULL; }
Type Min();
Type Max();
void Insert( const Type &x ) { Insert( x, root ); };
void Remove( const Type &x) { Remove( x, root ); };
private:
void MakeEmpty( BstNode<Type>*& ptr ); //将以ptr为根节点的二叉树置空
void Insert( const Type& x, BstNode<Type>*& ptr ); //插入
void Remove( const Type& x, BstNode<Type>*& ptr ); //删除
void PrintTree( BstNode<Type>* ptr ) const;
BstNode<Type>* Copy( const BstNode<Type>* ptr ); //复制
BstNode<Type>* Find( const Type& x, BstNode<Type> *ptr ) const; //搜索
BstNode<Type>* Min( BstNode<Type>* ptr ) const; //最小元素
BstNode<Type>* Max( BstNode<Type>* ptr ) const; //最大元素
private:
BstNode<Type>* root; //二叉搜索树的根节点
Type refValue; //数据输入停止标识
};
构造函数:从标准输入构造二叉搜索树,直到遇到输入停止标识
template <class Type>
BST<Type>::BST( Type value )
: refValue( value ), root( NULL )
{
Type x;
//重载>>
cin >> x;
//Type 需要重载!=,否则这块会失效
while ( x != refValue )
{
Insert( x, root );
cin >> x;
}
}
二叉搜索树置空:
MakeEmpty()删除参数中传入的结点,使用MakeEmpty()递归删除二叉搜索树种的每个结点。
//递归实现
template <class Type>
void BST<Type>::MakeEmpty( BstNode<Type>*& ptr )
{
if ( ptr == NULL )
return ;
if ( ptr->leftChild == NULL && ptr->rightChild == NULL )
{
delete ptr;
ptr = NULL;
return ;
}
else if ( ptr->leftChild != NULL )
MakeEmpty( ptr->leftChild );
else
MakeEmpty( ptr->rightChild );
}
二叉搜索树中查找元素
template <class Type>
BstNode<Type>* BST<Type>::Find( const Type& x, BstNode<Type>* ptr ) const
{
while ( ptr != NULL )
{
if ( ptr->data == x )
return ptr;
if ( x > ptr->data )
ptr = ptr->rightChild;
else
ptr = ptr->leftChild;
}
return ptr;
}
删除结点:递归实现,容易理解,容易实现
//删除结点的递归实现
//相对于非递归实现轻松许多
template <class Type>
void BST<Type>::Remove( const Type& x, BstNode<Type>*& ptr )
{
if ( ptr == NULL )
return ;
if ( ptr->data == x )
{
if ( ptr->leftChild == NULL && ptr->rightChild == NULL )
{
delete ptr;
ptr = NULL;
return ;
}
else if ( ptr->leftChild == NULL )
{
BstNode<Type>* temp = ptr;
ptr = ptr->rightChild;
delete temp;
return ;
}
else if ( ptr->rightChild == NULL )
{
BstNode<Type>* temp = ptr;
ptr = ptr->leftChild;
delete temp;
return ;
}
else
{
ptr->data = Min( ptr->rightChild )->data;
Remove( ptr->data, ptr->rightChild );
}
}
else if ( x > ptr->data )
{
Remove( x, ptr->rightChild );
}
else
{
Remove( x, ptr->leftChild );
}
}
删除结点:非递归实现,要考虑各种特殊情况,理解麻烦
//删除结点的非递归实现
//非递归实现比较麻烦
template <class Type>
void BST<Type>::Remove( const Type& x, BstNode<Type>*& ptr )
{
BstNode<Type>* fp = ptr;
BstNode<Type>* p = ptr;
//如果是删除根节点要特殊处理,麻烦
if ( ptr->data == x )
{
if ( ptr->leftChild == NULL && ptr->rightChild == NULL )
{
delete ptr;
ptr = NULL;
return ;
}
else if ( ptr->leftChild == NULL )
{
BstNode<Type>* temp = ptr;
ptr = temp->rightChild;
delete temp;
return ;
}
else if ( ptr->rightChild == NULL )
{
BstNode<Type>* temp = ptr;
ptr = temp->leftChild;
delete temp;
return ;
}
else
{
ptr->data = Min(ptr->rightChild)->data;
Remove( ptr->data, ptr->rightChild );
return ;
}
}
while ( p != NULL )
{
//找到目标,进行删除
if ( x == p->data )
{
BstNode<Type>* temp = p;
if ( p->leftChild == NULL )
{
//左孩子和右孩子同时为空,直接删除即可
if ( p->rightChild == NULL )
{
if ( p->data > fp->data )
fp->rightChild = NULL;
else
fp->leftChild = NULL;
delete p;
}
//左孩子为空,右孩子不为空,将右孩子替代根节点
else
{
if ( p->data > fp->data )
fp->rightChild = p->rightChild;
else
fp->leftChild = p->rightChild;
delete p;
}
}
//左孩子不为空,右孩子为空,将左孩子替代根节点
else if ( p->rightChild == NULL )
{
if ( p->data > fp->data )
fp->rightChild = p->leftChild;
else
fp->leftChild = p->leftChild;
delete p;
}
//左孩子和右孩子都不为空,选择右孩子中最小的元素替代根节点
else
{
//将p的键值改成p的右子树中最小的那个键值
p->data = Min( p->rightChild )->data;
//调用自己删除p的右子树中键值最小的那个结点
Remove( p->data, p->rightChild );
}
}
else if ( x > p->data )
{
fp = p;
p = p->rightChild;
}
else
{
fp = p;
p = p->leftChild;
}
}
}
求二叉搜索树键最小的结点
template <class Type>
BstNode<Type>* BST<Type>::Min(BstNode<Type>* ptr) const
{
if ( ptr == NULL )
return NULL;
while ( ptr->leftChild != NULL )
{
ptr = ptr->leftChild;
}
return ptr;
}
template <class Type>
Type BST<Type>::Min()
{
BstNode<Type>* result = Min( root );
if ( result == NULL )
return refValue;
else
return result->data;
}
求二叉搜索树键值最大的结点
template <class Type>
Type BST<Type>::Max()
{
BstNode<Type>* result = Max( root );
if ( result == NULL )
return refValue;
else
return result->data;
}
template <class Type>
BstNode<Type>* BST<Type>::Max( BstNode<Type>* ptr ) const
{
if ( ptr == NULL )
return NULL;
while ( ptr->rightChild != NULL )
{
ptr = ptr->rightChild;
}
return ptr;
}
插入,
//迭代实现
template <class Type>
void BST<Type>::Insert(const Type& x, BstNode<Type>*& ptr)
{
//若根节点为空,直接插入到根节点位置
if ( ptr == nullptr )
{
ptr = new BstNode<Type>( x );
return ;
}
//fp 插入点的父结点 p 未来的插入点
BstNode<Type>* p = ptr;
BstNode<Type>* fp = ptr;
//找到插入点
while ( p != nullptr )
{
fp = p;
if ( x > p->data )
p = p->rightChild;
else if ( x <= p->data )
p = p->leftChild;
}
//构造新结点
p = new BstNode<Type>( x );
//判断新节点是左子树还是右子树并且插入
if ( x > fp->data )
fp->rightChild = p;
else
fp->leftChild = p;
}
打印二叉搜索树并输出,即非递归实现二叉树的中序遍历
//中序遍历二叉搜索树
template <class Type>
void BST<Type>::PrintTree( BstNode<Type>* ptr ) const
{
if ( ptr == NULL )
return ;
//上一次对栈的操作是push还是pop
//用这个解决回溯时不能确定左子树是否被访问过的问题
//如果上一次对栈是push操作,说明栈顶部是一个新结点,新结点的左子树肯定没有被访问过
//如果上一次是pop操作,说明栈顶的元素的左子树已经被访问过了
bool pre_is_push = true;
stack<BstNode<Type>*> mid_order_stack; //迭代实现中序遍历二叉搜索树辅助栈
mid_order_stack.push( ptr );
while ( !mid_order_stack.empty() )
{
//show_stack( stack<BstNode<Type>*>( mid_order_stack ) );//脚手架 显示栈内容
//cout << mid_order_stack.top()->data << endl;//显示栈顶元素
if ( pre_is_push && mid_order_stack.top()->leftChild != NULL )
{
ptr = mid_order_stack.top()->leftChild;
mid_order_stack.push( ptr );
pre_is_push = true;
}
else
{
BstNode<Type>* temp_mid = mid_order_stack.top();
mid_order_stack.pop();
pre_is_push = false;
if ( temp_mid->rightChild != NULL )
{
mid_order_stack.push( temp_mid->rightChild );
pre_is_push = true;
}
cout << temp_mid->data << " ";
}
}
cout << endl;
}
测试主函数
int main( void )
{
BST<int> int_bstree( 0 );
cout << int_bstree.Max() << endl;
cout << int_bstree.Min() << endl;
int_bstree.PrintTree();
int_bstree.Remove( 67 );
cout << int_bstree.Find( 5 ) << endl;
cout << int_bstree.Find( 100 ) << endl;
int_bstree.PrintTree();
int_bstree.MakeEmpty();
int_bstree.PrintTree();
}