数据结构 - 二叉排序树

#include <stdio.h>    
#include <stdlib.h>    
typedef int ElemType;    
typedef struct BiTNode  
{    
    ElemType data;    
    struct BiTNode *lchild,*rchild;    
}BiTNode,*BiTree;    
int SearchBST(BiTree T,ElemType key,BiTree f,BiTree *p)  
{  
    if(!T)  
    {  
        *p = f;  
        return 0;  
    }  
    else  
    {  
        if(key == T->data)  
        {  
            *p = T;  
            return 1;  
        }  
        else  
        {  
            if(key < T->data)  
            {   
                return SearchBST(T->lchild,key,T,p);  
            }  
            else  
            {  
                return SearchBST(T->rchild,key,T,p);  
            }  
        }  
    }  
}  
int InsertBST(BiTree *T,ElemType key)  
{  
    BiTree p,s;  
    if(!SearchBST(*T,key,NULL,&p))  
    {  
        s = (BiTree)malloc(sizeof(BiTNode));  
        s->data = key;  
        s->lchild = s->rchild =NULL;  
        if(!p)  
        {  
            *T = s;  
        }  
        else  
        {  
            if(key < p->data)  
            {  
                p->lchild = s;  
            }  
            else  
            {  
                p->rchild = s;  
            }  
        }  
        return 1;  
    }  
    else  
    {  
        return 0;  
    }  
      
}  
int Delete(BiTree *p)  
{  
    BiTree q,s;  
    if((*p)->rchild == NULL)  //右子树为空
    {  
        q = *p;  
        *p = (*p)->lchild;  
        free(q);  
    }  
    else if((*p)->lchild == NULL)  //左子树为空
    {  
         q = *p;  
         *p = (*p)->rchild;  
         free(q);  
     }  
    else  
        {  
            q = *p;  
            s = (*p)->lchild;  
            while(s->rchild)  
            {  
                q = s;  
                s = s->rchild;  
            }  
            (*p)->data = s->data;  
            if(q != *p)  //s指向要删除节点的直接前驱,且s没有右子树(可模拟试试)
            {  
                q->rchild = s->lchild;  
            }  
            else  
            {  
                q->lchild = s->lchild;  
            }  
            free(s);  
        }  
    }  
    return 1;  
}  
//删除一个节点的操作
int DeleteBST(BiTree *T,ElemType key)  
{  
    if(!*T)  
    {  
        return 0;  
    }  
    else  
    {  
        if(key == (*T)->data)  
        {  
            return Delete(T);  
        }  
        else  
        {  
            if(key < (*T)->data)  
            {   
                return DeleteBST(&(*T)->lchild,key);  
            }  
            else  
            {  
                return DeleteBST(&(*T)->rchild,key);  
            }  
        }  
    }  
}  
按数据结构书本,难点是删除操作:
当删除节点左子树或右子树为空,则直接删除,修改其父节点右左指针。
当删除节点左右子树均不为空,有两种方法:
1.将删除节点的直接前驱代替(中序遍历),并将前驱节点的左孩子放其父节点右孩子位置。
2.将删除节点的左子树放其父节点左子树位置,将其右子树放其直接前驱右子树位置。(其实不难)


/***************************************************************************/


#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);  
    }  
}  




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值