数据结构——二叉排序树

创建、查找、删除

codeblocks 17 通过

#include <iostream>
#define KeyType int
#define InfoType char
using namespace std;

typedef struct
{
    KeyType key;    // 关键字项
    InfoType otherinfo;  // 其他数据项
}ElemType;  // 每个节点的数据类型
typedef struct BSTNode
{
    ElemType data;  // 节点的数据项
    struct BSTNode *lchild, *rchild;
}BSTNode,*BSTree;

void InsertBST(BSTree &T, ElemType e)
{
    if(!T)  // T根节点为空
    {
        BSTree S = new BSTNode;
        S->data = e;
        S->lchild = S->rchild = NULL;
        T=S;
    }
    else if(e.key < T->data.key)
        InsertBST(T->lchild,e);
    else if(e.key > T->data.key)
        InsertBST(T->rchild,e);
}

void CreateBSTree(BSTree &T)
{
    T = NULL;   // 初始化为空树
    int n=15;
    //cin>>n:
    while(n>0)
    {
        ElemType value;
        cin>>value.key;
        InsertBST(T,value);
        n--;
    }
    //cout<<"Create Done !"<<endl;
}

BSTree SearchBST(BSTree &T, KeyType key)
{
    if((!T)||key==T->data.key)
        return T;   // 查找结束 返回目标节点或者空指针
    else if(key<T->data.key)
        return SearchBST(T->lchild,key);    // 在左子树中继续查找
    else
        return SearchBST(T->rchild,key);    // 在右子树中继续查找
}

void InOrderTraverse(BSTree T)
{// 中序递归遍历
    if(T)
    {
        InOrderTraverse(T->lchild);
        cout<<T->data.key<<" ";
        InOrderTraverse(T->rchild);
    }
}

void DeleteBST(BSTree &T, KeyType key)
{// 从二叉排序树T中删除关键字等于key的节点
    BSTree p = T, f=NULL, q;    // 初始化
    /*------下面的while循环从根开始查找关键字等于key的节点--------*/
    while(p)
    {
        if(p->data.key == key)
            break;
        f = p;
        if(p->data.key > key)
            p = p->lchild;
        else
            p = p->rchild;
    }
    /*--------分别考虑三种情况,p所指的子树内部:左右子树都不为空,无左子树,无右子树---------*/
    q = p;
    if((p->lchild)&&(p->rchild))    // 左右子树都不为空
    {
        BSTree s = p->lchild;
        while(s->rchild)    // 查找p的左子树的最右节点,即p的直接前驱
        {
            q=s;s=s->rchild;
        }
        p->data=s->data;    // 将s的data 赋值给要删除的节点p,p不能直接delete,需要保持p的左右子树关系
        if(q!=p)    // 如果pq不相同,说明s有右子树
            q->rchild=s->lchild;
        else    // qp相同,说明s没有右子树
            q->lchild=s->lchild;
        delete s;
        return; // 删除结束!!!
    }
    else if(!p->rchild)   // 无右子树,只需要重接左子树
    {
        p = p->lchild;
    }
    else if(!p->lchild)   // 无左子树,只需要重接右子树
    {
        p = p->rchild;
    }
    /*-------将p所指的子树挂接到其双亲节点*f相应位置-----------*/
    if(!f)  T=p;    // 如果删除的是根节点
    else if(q==f->lchild)   //  q是f的左子树,p接到f的左子树位置
        f->lchild=p;
    else    // q是f的右子树,p接到f的右子树位置
        f->rchild=p;
    delete q;
}

int main()
{
    BSTree T;
    CreateBSTree(T);
    InOrderTraverse(T);
    cout<<"\n";
    BSTree p;
    KeyType key;
    cin>>key;
    p = SearchBST(T,key);
    if(p)
        cout<<"查找成功!"<<endl;
    else
        cout<<"not find it!"<<endl;
    cin>>key;
    DeleteBST(T,key);
    InOrderTraverse(T);

}


/*
test data:
输入:
1 5 4 2 3 6 8 7 9 11 14 13 12 16 19
输出:
1 2 3 4 5 6 7 8 9 11 12 13 14 16 19
输入:
19
输出:
查找成功!
输入:
14
输出:
1 2 3 4 5 6 7 8 9 11 12 13 19 16

*/

附图便于思考删除算法

小甲鱼老师的代码,我加了注释:

int Delete(BSTree &p)
{
    BSTree q, s;
    /*-----待删除的节点只有左或右子树----*/
    if(p->rchild == NULL)
    {
        q = p;
        p = p->lchild;
        delete q;
    }
    else if(p->lchild == NULL)
    {
        q = p;
        p = p->rchild;
        delete q;
    }
    /*-----待删除的节点有左和右子树-------*/
    else
    {
        q = p;
        s = p->lchild;

        while(s->rchild)
        {// 查找p的直接前驱,s记录,q是s的双亲
            q = s;
            s = s->rchild;
        }

        p->data.key = s->data.key;  // 数据替换

        if(q != p)  // qp不想同,说明p的左子树有右子树
            q->rchild = s->lchild;
       else // qp相同,说明p的左子树没有右子树
            q->lchild = s->lchild;

       delete s;
    }

    return 1;
}
int DeleteBST_JiaYu(BSTree &T, KeyType key)
{// 返回删除结果,该函数也可通过调用search函数进行查找,再删除。
    if(!T)
        return -1;
    else
    {
        if(key == T->data.key)
            return Delete(T);
        else if(key>T->data.key)
            return DeleteBST_JiaYu(T->rchild,key);
        else
            return DeleteBST_JiaYu(T->lchild,key);
    }
}

 另附图:

 

完整代码code

// 二叉排序树 @ChenYe 2018/12/02
#include <iostream>
#define KeyType int
#define InfoType char
using namespace std;

typedef struct
{
    KeyType key;    // 关键字项
    InfoType otherinfo;  // 其他数据项
}ElemType;  // 每个节点的数据类型
typedef struct BSTNode
{
    ElemType data;  // 节点的数据项
    struct BSTNode *lchild, *rchild;
}BSTNode,*BSTree;

void InsertBST(BSTree &T, ElemType e)
{
    if(!T)  // T根节点为空
    {
        BSTree S = new BSTNode;
        S->data = e;
        S->lchild = S->rchild = NULL;
        T=S;
    }
    else if(e.key < T->data.key)
        InsertBST(T->lchild,e);
    else if(e.key > T->data.key)
        InsertBST(T->rchild,e);
}

void CreateBSTree(BSTree &T)
{
    T = NULL;   // 初始化为空树
    int n=15;
    //cin>>n:
    while(n>0)
    {
        ElemType value;
        cin>>value.key;
        InsertBST(T,value);
        n--;
    }
    //cout<<"Create Done !"<<endl;
}

BSTree SearchBST(BSTree &T, KeyType key)
{
    if((!T)||key==T->data.key)
        return T;   // 查找结束 返回目标节点或者空指针
    else if(key<T->data.key)
        return SearchBST(T->lchild,key);    // 在左子树中继续查找
    else
        return SearchBST(T->rchild,key);    // 在右子树中继续查找
}

void InOrderTraverse(BSTree T)
{// 中序递归遍历
    if(T)
    {
        InOrderTraverse(T->lchild);
        cout<<T->data.key<<" ";
        InOrderTraverse(T->rchild);
    }
}

void DeleteBST(BSTree &T, KeyType key)
{// 从二叉排序树T中删除关键字等于key的节点
    BSTree p = T, f=NULL, q;    // 初始化
    /*------下面的while循环从根开始查找关键字等于key的节点--------*/
    while(p)
    {
        if(p->data.key == key)
            break;
        f = p;
        if(p->data.key > key)
            p = p->lchild;
        else
            p = p->rchild;
    }
    /*--------分别考虑三种情况,p所指的子树内部:左右子树都不为空,无左子树,无右子树---------*/
    q = p;
    if((p->lchild)&&(p->rchild))    // 左右子树都不为空
    {
        BSTree s = p->lchild;
        while(s->rchild)    // 查找p的左子树的最右节点,即p的直接前驱
        {
            q=s;s=s->rchild;
        }
        p->data=s->data;    // 将s的data 赋值给要删除的节点p,p不能直接delete,需要保持p的左右子树关系
        if(q!=p)    // 如果pq不相同,说明s有右子树
            q->rchild=s->lchild;
        else    // qp相同,说明s没有右子树
            q->lchild=s->lchild;
        delete s;
        return; // 删除结束!!!
    }
    else if(!p->rchild)   // 无右子树,只需要重接左子树
    {
        p = p->lchild;
    }
    else if(!p->lchild)   // 无左子树,只需要重接右子树
    {
        p = p->rchild;
    }
    /*-------将p所指的子树挂接到其双亲节点*f相应位置-----------*/
    if(!f)  T=p;    // 如果删除的是根节点
    else if(q==f->lchild)   //  q是f的左子树,p接到f的左子树位置
        f->lchild=p;
    else    // q是f的右子树,p接到f的右子树位置
        f->rchild=p;
    delete q;
}

int Delete(BSTree &p)
{
    BSTree q, s;
    /*-----待删除的节点只有左或右子树----*/
    if(p->rchild == NULL)
    {
        q = p;
        p = p->lchild;
        delete q;
    }
    else if(p->lchild == NULL)
    {
        q = p;
        p = p->rchild;
        delete q;
    }
    /*-----待删除的节点有左和右子树-------*/
    else
    {
        q = p;
        s = p->lchild;

        while(s->rchild)
        {// 查找p的直接前驱,s记录,q是s的双亲
            q = s;
            s = s->rchild;
        }

        p->data.key = s->data.key;  // 数据替换

        if(q != p)  // qp不想同,说明p的左子树有右子树
            q->rchild = s->lchild;
       else // qp相同,说明p的左子树没有右子树
            q->lchild = s->lchild;

       delete s;
    }

    return 1;
}
int DeleteBST_JiaYu(BSTree &T, KeyType key)
{// 返回删除结果,该函数也可通过调用search函数进行查找,再删除。
    if(!T)
        return -1;
    else
    {
        if(key == T->data.key)
            return Delete(T);
        else if(key>T->data.key)
            return DeleteBST_JiaYu(T->rchild,key);
        else
            return DeleteBST_JiaYu(T->lchild,key);
    }
}


int main()
{
    BSTree T;
    CreateBSTree(T);
    InOrderTraverse(T);
    cout<<"\n";
    BSTree p;
    KeyType key;
    cin>>key;
    p = SearchBST(T,key);
    if(p)
        cout<<"查找成功!"<<endl;
    else
        cout<<"not find it!"<<endl;
    cin>>key;
    DeleteBST(T,key);
    InOrderTraverse(T);


    cout<<"\n新增测试,请输入要删除的数据:\n";
    cin>>key;
    DeleteBST_JiaYu(T,key);
    InOrderTraverse(T);

}


/*
test data:
输入:
1 5 4 2 3 6 8 7 9 11 14 13 12 16 19
输出:
1 2 3 4 5 6 7 8 9 11 12 13 14 16 19
输入:
19
输出:
查找成功!
输入:
14
输出:
1 2 3 4 5 6 7 8 9 11 12 13 19 16

*/

 测试

猜你喜欢

转载自blog.csdn.net/qq_41420747/article/details/84711854