二叉排序树的基本算法

        写了二叉排序树,基本的插入,查找,删除运算,下面是我的详细代码:

 

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

typedef  struct BiTNode{//定义二叉排序树的结构 
         int data;//值 
         struct BiTNode *lchild,*rchild;//左右孩子 
         }BiTNode,*BiTree;

void inorder(BiTree T);  //中序遍历 
int DeleteBST(BiTree T,int key);   //删除特定元素   
int SearchBST(BiTree u,int key);//查找元素 
BiTree InsertBST(BiTree T,int key);//插入元素

int main()//测试函数 
{
    int i,data,n,m;
    BiTree tree = NULL;//定义BiTNode 型的指针 
    
    printf("Input your data:");
    for(i = 0; i < 7; i++)//输入值 
    {
          scanf("%d",&data);
          tree = InsertBST(tree,data);//构造树 
    }
    
    printf("中序遍历结果:"); 
    inorder(tree);
    printf("\n"); 
    
    printf("输入要查找的元素:");
    scanf("%d",&n); 
    printf("查找结果:");
    printf("%d\n",SearchBST(tree,n));
    
    printf("输入要删除的元素:");
    scanf("%d",&m);
    DeleteBST(tree,m);
    inorder(tree);
     
    system("pause");
    return 0;
}

int SearchBST(BiTree u,int key)//二叉排序树、查找的递归算法 
{
    BiTree p = u;
    
    if(!p)
          return 0;
    else if(key == p->data)
          return 1;
    else if(key > p->data)
          return SearchBST(p->rchild,key);
    else
          return SearchBST(p->lchild,key);
}

BiTree InsertBST(BiTree T,int key)//二叉排序树的插入 
{
       BiTree f = T,p = T;
       
       while(p)
       {
               if(p->data == key)//如果待插元素等于根结点的值 ,则不用插入 
                     return T;//返回根结点 
               f = p;//用f记下查找路径上的最后一个访问的结点 
               p = (key < p->data)? p->lchild:p->rchild;//如果根结点值与待插元素不等,重置p,根据大小关系 
       }
       
       p = (BiTNode *)malloc(sizeof(BiTNode));//申请待插元素所需空间 
       p->data = key;//待插元素赋给此结点 
       p->lchild = p->rchild = NULL;//将插入的元素所在结点的左右孩子均置为空 
               
       //插入操作: 
       if(T == NULL)//T为空,吧P赋给T 
            T = p;
       else if(key < f->data)//否则,插入待插元素 
            f->lchild = p;//根据大小关系 
       else 
            f->rchild = p;//根据大小关系插入 
       
       return T;//返回树根 
}    

void inorder(BiTree T)//根据二叉排序树的特点,中序遍历后为顺序输出,元素已经排好序 
{
     if(T)
     {
          inorder(T->lchild); 
          printf("%d ",T->data);
          inorder(T->rchild);
     }
}

int DeleteBST(BiTree T,int key)//删除算法,删除其中一个关键字为key的结点 
{
    BiTree p = T,f,q,s,root = T;
    
    while(p)
    {
            if(p->data == key)//找出关键字为key的结点 
                break;
            
            f = p;//记录关键字key结点的父结点 
            p = (key < p->data)? p->lchild:p->rchild;//在P的左右子树中寻找 
    }
    
    if(!p)
          return 0;//二叉排序树中无关键字为key的结点 
    
    if(p->lchild == NULL && p->rchild == NULL)//P没有左右子树 
    {
         if(p == T)
              T = NULL;//删除的是根结点 
         else if(p == f->lchild)//f为关键字为key的结点p的父结点 
              f->lchild = NULL;//将f的左孩子置为空 
         else
              f->rchild = NULL;//将f的右孩子置为空 
         free(p);//删除结点p 
    }
    else if(p->lchild == NULL && p->rchild != NULL)
    {//P无左子树,有右子树 
         if(f->lchild == p)
              f->lchild = p->rchild;//将p的右子树链接到其父结点的左链上
         else
              f->rchild = p->rchild;//将p的右子树链接到其父结点的右链上
         free(p);
    }
    else if(p->lchild != NULL && p->rchild == NULL)
    {//p有左子树无右子树
         if(f->lchild == p)
              f->lchild = p->lchild;//将p的左子树链接到其父结点的左链上
         else
              f->rchild = p->lchild;//将p的左子树链接到其父结点的右链上
         free(p);
    }
    else if(p->lchild != NULL && p->rchild != NULL)//p既有左子树又有右子树
    {
         q = p;
         s = p->lchild;//转左
         
         while(s->rchild)
         {//然后向右到尽头
              q = s;
              s = s->rchild;//s指向被删节点的"前驱"(中序前驱)
         }
         
         p->data = s->data;//以p的中序前趋结点s代替p(即把s的数据复制到p中)
         
         if(q != p)
              q->rchild = s->lchild;//重接q的右子树
         else
              q->lchild = s->lchild;//重接q的左子树。
         free(s);
    }
}    
        


       其他操作我觉得都容易,在删除结点时,情况有点复杂,下面是一点小解析:
              
    
      假设在二叉排序树上被删除结点时*p(指向节点的指针为p),其双亲结点为*f(结点指针为f),且不是一般性,可设*p是*f的左孩子。

     分三种情况进行:

      1. 若p结点为叶子节点,即p没有左右孩子,由于删除叶子节点不破坏整棵树的结构,则只需修改双亲节点的指针即可。

      2. 若p结点只有左孩子或者只有右孩子,此时只要将其左孩子或右孩子直接成为其双亲结点f的左子树即可。

      3. 若p结点左右子树均不空,先找到*p的中序前趋结点*s(注意*s*p的左子树中的最右下的结点,它的右链域为空),然后有两种做法:

其一是令p的左子树为f的左子树,而p的右子树为s的右子树;其二是令p的直接前驱(或直接后继)代替p,然后再从二叉排序树中删去它的直接前驱(或直接后继)。
       


     
   
                          
       
    
   

 

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值