二叉搜索树

来源:互联网 发布:网络空间用什么来描绘 编辑:程序博客网 时间:2024/05/16 23:41

二叉搜索树定义

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需要访问私有成员datapublic:    //构造函数    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();}
原创粉丝点击