二叉排序树的操作(建立、插入、删除和查找)

二叉排序树的建立、插入、删除和查找

#include <stdio.h>
#include <stdlib.h>

typedef struct node
{
    int key;
    struct node *lchild,*rchild;
}BSTNode;

//二叉排序树插入操作递归算法
BSTNode *InsertBST1(BSTNode *T, int key)
{
    BSTNode *p, *q = T;

    //p为待插入的新结点
    p = (BSTNode *)malloc(sizeof(BSTNode));
    p->key = key;
    p->lchild = p->rchild = NULL;

    if(T == NULL) //原树为空
        T = p; //新插入的结点为新的根

    //原树非空时将新结点p作为q的左孩子或右孩子插入
    else
    {
        if(key == q->key)
            return T;

        if(key < q->key)
        {
            if(q->lchild ==NULL)
                q->lchild = p;
            else
                InsertBST1(q->lchild, key);
        }

        if(key > q->key)
        {
            if(q->rchild ==NULL)
                q->rchild = p;
            else
                InsertBST1(q->rchild, key);
        }
    }
    return T;
}

////二叉排序树插入操作非递归算法
BSTNode *InsertBST2(BSTNode *T, int key)
{
    BSTNode *f, *p = T;

    //查找插入位置
    while(p)
    {
        if(key == p->key)
            return T;//无须插入

        f = p;//记录访问的结点
        if(key < p->key)
            p = p->lchild;
        else
            p = p->rchild;
        //若key<p->key,则在左子树中查找,否则在右子树中查找
    }

    //p为待插入的新结点
    p = (BSTNode *)malloc(sizeof(BSTNode));
    p->key = key;
    p->lchild = p->rchild = NULL;

    if(T == NULL) //原树为空
        T = p; //新插入的结点为新的根

    //原树非空时将新结点q作为p的左孩子或右孩子插入
    else
    {
        if(key < f->key)
            f->lchild = p;
        else f->rchild = p;
    }

    return T;
}

//二叉排序树删除操作
void DelBST(BSTNode *T,int key)
{
    BSTNode *p = T, *f, *q, *s;
    while(p)
    {
        if(p->key == key) break; //找到关键字为key的结点
        f=p;//记下关键字key节点的父节点
        p=(key < p->key)? p->lchild : p->rchild;//分别在*p的左、右子树中查找
    }
    if(!p) return;//二叉排序树中无关键字为key的结点
    if(p->lchild == NULL && p->rchild == NULL)//p无左子树无右子树
    {
        if(p == T) T = NULL;//删除的是根节点
        else
            if(p == f->lchild)
                f->lchild = NULL;
            else
                f->rchild = NULL;
    }
    else if(p->lchild == NULL && p->rchild != NULL)//p无左子树有右子树
    {
        if(f->lchild == p)
            f->lchild = p->rchild;
        else
            f->rchild = p->rchild;
    }
    else if(p->rchild == NULL && p->lchild != NULL)//p有左子树无右子树
    {
        if (f->lchild == p)
            f->lchild = p->lchild;
        else
            f->rchild = p->lchild;
    }
    else if(p->lchild != NULL && p->rchild != NULL)//p既有左子树又有右子树
    {
        q = p;
        s = p->lchild;//转左
        while(s->rchild)
        {//然后向右到尽头
            q = s;
            s = s->rchild;//s指向被删节点的“前驱”(中序前驱)
        }
        p->key = s->key;//以p的中序前趋结点s代替p(即把s的数据复制到p中)
        if(q != p)
            q->rchild = s->lchild;//重接q的右子树
        else
            q->lchild = s->lchild;//重接q的左子树。
    }
}


//创建二叉排序树
BSTNode *CreateBST()
{
    BSTNode *T = NULL; //初始时T为空树
    int key;
    printf("请输入一系列数,以0结尾:");
    while(1)
    {
        scanf("%d", &key);//读入一关键字
        if(key == 0)
            break;//假设key=0是输入结束标志
        else
            T = InsertBST1(T, key); //使用递归算法,将key插入二叉排序树T,改为 T = InsertBST2(T, key);为非递归插入算法
    }
    return T; //返回建立的二叉排序树的根指针
}

//二叉排序树查找递归算法
int BSTsearch1(BSTNode *T, int data)
{
    BSTNode *p = T;
    if(!p)
        return 0;
    else if(p->key == data)
            return 1;
        else if(p->key > data)
                return BSTsearch1(p->lchild, data);
            else
                return BSTsearch1(p->rchild, data);
}

//二叉排序树查找非递归算法
int BSTsearch2(BSTNode *T, int data)
{
    BSTNode *p = T;
    while(p)
    {
        if(p->key == data)
            return 1;
        p = (p->key > data)? p->lchild : p->rchild;
    }
    return 0;
}

//中序遍历得到的是一个有序的序列,实现了排序功能
void Inorder(BSTNode *T)
{
    if(T)
    {
        Inorder(T->lchild);
        printf("%d ",T->key);
        Inorder(T->rchild);
    }
}

int main()
{
    BSTNode *T = NULL;
    int data1,data2;
    T = CreateBST();

    printf("以上述数建立的二叉排序树,中序遍历的结果:");
    Inorder(T);

    printf("\n输入待搜索的数据data1=");
    scanf("%d", &data1);
    //递归算法查找
    if(BSTsearch1(T, data1))
        printf("%d存在\n");
    else
        printf("%d不存在\n");
    //非递归算法查找
    if(BSTsearch2(T, data1))
        printf("%d存在");
    else
        printf("%d不存在");


    printf("\n输入待删除的数据data2=");
    scanf("%d", &data2);
    DelBST(T,data2);
    printf("删除后的二叉排序树,中序遍历的结果:");
    Inorder(T);

    return 0;
}

对于删除操作的一点小改动的程序

//二叉排序树删除操作
void DelBST(BSTNode *T,int key)
{
    BSTNode *p = T, *f, *q, *s;
    while(p)
    {
        if(p->key == key) break; //找到关键字为key的结点
        f=p;//记下关键字key节点的父节点
        p=(key < p->key)? p->lchild : p->rchild;//分别在*p的左、右子树中查找
    }
    if(!p) return;//二叉排序树中无关键字为key的结点
    if(p->lchild == NULL && p->rchild == NULL)//p无左子树无右子树
    {
        if(p == T) T = NULL;//删除的是根节点
        else
            if(p == f->lchild)
                f->lchild = NULL;
            else
                f->rchild = NULL;
    }
    else if(p->lchild == NULL && p->rchild != NULL)//p无左子树有右子树
    {
        if(f->lchild == p)
            f->lchild = p->rchild;
        else
            f->rchild = p->rchild;
    }
    else if(p->rchild == NULL && p->lchild != NULL)//p有左子树无右子树
    {
        if (f->lchild == p)
            f->lchild = p->lchild;
        else
            f->rchild = p->lchild;
    }
    else if(p->lchild != NULL && p->rchild != NULL)//p既有左子树又有右子树
    {
        q = p;
        s = p->lchild;
        if(s->rchild == NULL)
        {
            q->key = s->key;
            q->lchild = s->lchild;//重接q的左子树
        }
        else
        {
            while(s->rchild)
            {//然后向右到尽头
                q = s;
                s = s->rchild;//s指向被删节点的“前驱”(中序前驱)
            }
            p->key = s->key;//以p的中序前趋结点s代替p(即把s的数据复制到p中
            q->rchild = s->lchild;//重接q的右子树
        }
    }
}

 

    原文作者:二叉查找树
    原文地址: https://blog.csdn.net/sjyu_ustc/article/details/10185851
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞