zoukankan      html  css  js  c++  java
  • 二叉排序树(Binary Sort Tree)

    二叉排序树(Binary Sort Tree)又称二叉查找树,是一种排序和查找都很有用的特殊二叉树。
    BST 满足 左节点的值<根节点的值<右节点的值。根据这个原理,我们可以推断:BST的中序遍历必定是严格递增的。

    如图一棵二叉树,是一棵BST。我们可以明显看到他的中序遍历为09,17,23,45,53,60,70,75,78,88,94。(因为左<中<右)

    下面是BST的实现,包括BST的插入,创建,删除,遍历

    //BST.h
    #include<iostream>
    using namespace std;
    template<typename T>
    struct node
    {
        T key;
        //char word;
    };
    template<typename T>
    struct BSTNode
    {
        node<T> data;
        BSTNode<T> *lchild;
        BSTNode<T> *rchild;
    };
    template<typename T>
    class BSTree
    {
    private:
        BSTNode<T> *bt;//根指针
    public:
        BSTree();//构造函数
        ~BSTree();//析构函数
        BSTNode<T>* & GetRoot();//得到跟节点
        void Clear(BSTNode<T>* &p);//删除节点,释放空间
        bool BSTInsert(BSTNode<T>* &p,T key);//在p指向的二叉树中有序插入 数据元素为key的节点
        void Create(int n);//创建含有n个元素的BST
        void PreTraBST(BSTNode<T> *p);//前序遍历
        void InTraBST(BSTNode<T> *p);//中序遍历,输出的BST是从小到大排列的
        void SearchBST(BSTNode<T> *p,T key);//在p指向的二叉树中查找 是否存在数据元素key
        int Delete(BSTNode<T> * &p);//删除节点p
        int DeleteBST(BSTNode<T>* &p,T key);//在p指向的BST中删除数据元素key,并保证删除后的二叉树还是BST
    };
    template<typename T>
    BSTree<T>::BSTree()
    {
        bt=NULL;
    }
    template<typename T>
    BSTree<T>::~BSTree()
    {
        BSTNode<T> *p;
        p=bt;
        Clear(p);
    }
    template<typename T>
    BSTNode<T>* & BSTree<T>::GetRoot()
    {
        return bt;
    }
    template<typename T>
    void BSTree<T>::Clear(BSTNode<T> * &p)
    {
        if(p)
        {
            Clear(p->lchild);
            Clear(p->rchild);
        }
        getchar();
        delete p;
        cout<<"删除节点"<<p<<"的空间"<<endl;
    }
    template<typename T>
    bool BSTree<T>::BSTInsert(BSTNode<T>* &p,T key)//在p指向的二叉树中有序插入数据元素key
    {
        if(p==NULL) //p为空树,创建数据元素为key的新节点,并将p指向该节点
        {
            BSTNode<T> *s=new BSTNode<T>;
            s->data.key=key;
            s->lchild=s->rchild=NULL;
            p=s;
            return true;
        }
        else if(key>p->data.key)//key 大于节点p->data.key,递归遍历右子树。BST的右子树一定大于左子树
            BSTInsert(p->rchild,key);
        else if(key<p->data.key)//key 小于节点p->data.key,遍历左子树。
            BSTInsert(p->lchild,key);
        else if(key==p->data.key)
        {
            cout<<"插入数据已存在"<<endl;
            return false;
        }
    }
    template<typename T>
    void BSTree<T>::Create(int n)
    {
        T key;
        bt=NULL; 
        cout<<"输入"<<n<<"个不同的数据元素"<<endl;
        for(int i=0;i<n;i++)
        {
            cin>>key;
            BSTInsert(bt,key);
        }
    }
    template<typename T>
    void BSTree<T>::PreTraBST(BSTNode<T> *p)
    {
        if(p)
        {
            cout<<p->data.key<<" ";
            PreTraBST(p->lchild);
            PreTraBST(p->rchild);
        }
    }
    template<typename T>
    void BSTree<T>::InTraBST(BSTNode<T> *p) //中序输出时数据元素一定是按升序排列的
    {
        if(p)
        {
            InTraBST(p->lchild);
            cout<<p->data.key<<" ";
            InTraBST(p->rchild);
        }
    
    }
    template<typename T>
    void BSTree<T>::SearchBST(BSTNode<T> *p,T key)//在BST中查找数据元素key 是否存在,存在则找出其中的p,并且删除
    {
        if(p==NULL||p->data.key==key)
        {
            if(p==NULL)
            {
                cout<<"查找的数据元素不存在"<<endl;
            }
            else if(p->data.key==key)
            {
                cout<<"找到数据元素"<<key<<endl;
            }
        }
        else if(key>p->data.key)
        {
            SearchBST(p->rchild,key);
        }
        else if(key<p->data.key)
        {
            SearchBST(p->lchild,key);
        }
            
    }
    template<typename T>
    int BSTree<T>::Delete(BSTNode<T>* &p)//删除节点p
    {
        BSTNode<T> *q,*s;
        if(p->rchild==NULL)//待删除的节点p没有右子树
        {
            q=p;
            p=p->lchild;
            cout<<"成功删除"<<endl;
            delete q;
            
        }
        else if(p->lchild==NULL)//待删除的节点p没有左子树
        {
            q=p;
            p=p->rchild;
            cout<<"成功删除"<<q->data.key<<endl;
            delete q;
            
        }
        else if(p->lchild==NULL&&p->rchild==NULL)
        {
            
            delete p;
            cout<<"成功删除"<<endl;
        }
        else//待删除的节点p的左右节点都存在
        {
            q=p;
            s=p->lchild;
            while(s->rchild)//在p节点的左子树中寻找其前驱节点。即最右节点。
            {
                q=s;
                s=s->rchild;//最终s指向待删除节点的前驱节点
            }
            p->data=s->data;//将前驱节点赋值给p节点
            if(q!=p)
                q->rchild=s->lchild;
            else q->lchild=s->lchild;
            delete s;
            cout<<"成功删除"<<endl;    
        }
        return true;
    }
    template<typename T>
    int BSTree<T>::DeleteBST(BSTNode<T>* &p,T key)
    {
        if(p==NULL)
        {
            cout<<"二叉树为空,无法删除"<<endl;
            return false;
        }
        else
        {
            if(key==p->data.key)
                return Delete(p);
            else if(key>p->data.key)
                return DeleteBST(p->rchild,key);
            else
                return DeleteBST(p->lchild,key);
        }
    }
    //BST-main.cpp
    #include<iostream>
    using namespace std;
    #include"BST.h"
    int main(void)
    {
        int n,key,flag;
        BSTree<int> bst;
    
        cout<<"输入二叉树的数据元素个数:";
    
        cin>>n;
        bst.Create(n);//Create创建的是一个排序二叉树
        cout<<"先序遍历输出:";
        bst.PreTraBST(bst.GetRoot());
        cout<<endl;
    
        cout<<"中序遍历输出:";//中序遍历一定是有序的
        bst.InTraBST(bst.GetRoot());
        cout<<endl;
    
        cout<<"输入要查找的元素:";
        cin>>key;
        bst.SearchBST(bst.GetRoot(),key);
    
        flag=1;
        while(flag)
        {
            cout<<"输入要删除的元素(-1为结束标志):";
            cin>>key;
            if(key!=-1)
            {
                bst.DeleteBST(bst.GetRoot(),key);
            }
            else
                flag=0;
    
            cout<<"先序遍历输出:";
            bst.PreTraBST(bst.GetRoot());
            cout<<endl;
    
            cout<<"中序遍历输出:";//中序遍历一定是有序的
            bst.InTraBST(bst.GetRoot());
            cout<<endl;
        }
        getchar();
    }

    测试结果如下:

    关于BST 删除数据元素的理解

    1.待删除的节点p没有右子树  p->rchild==NULL

    2.待删除的节点p没有左子树 p->lchild==NULL

    3.左右子节点都不存在  p->lchild==NULL&&p->rchild==NULL

    直接删除

    4.左右子节点都存在   p->lchild!=NULL&&p->rchild!=NULL

    4.1   q!=p  其中s指向待删除节点的前驱节点,然后用77替换78,并将75指向76

          

    4.2  p==q  将节点70赋值给节点80

  • 相关阅读:
    关于头文件
    函数重载和函数模板
    引用和内联函数
    OpenCV中图像处理
    MFC中关于子进程创建和关闭操作
    MFC中的CListControl控件
    MFC中Picture控件显示图像
    MFC CString 和int相互转化
    MFC下拉框
    MFC中关于CListBox控件添加水平滚动条
  • 原文地址:https://www.cnblogs.com/qianwen/p/3816574.html
Copyright © 2011-2022 走看看