二叉搜索树

#include <stdio.h>
#include <stdlib.h>
typedef struct node
{

    int element;
    struct node* Lchild,*Rchild;
}node;
typedef struct tree
{
    struct node *root;
}tree;
node * creat(tree *a)
{
    a->root=NULL;
}
 void  Insert(tree *a,int x)
{
    node *r,*p,*q;
    r=(node*)malloc(sizeof(node));//生成临时节点存储需要插入的值
            r->element=x;
            r->Lchild=NULL;
            r->Rchild=NULL;
            if (!(a->root))//如果根节点不为空(根节点就没有左子树右子树的说法了,直接另根节点为r即可)
            {
            a->root=r;
            return;
            }
            p=a->root;
           while(p!=NULL)
    {

        q=p;//记录下父节点
        if (x<p->element)//如果小于该节点的权值,扫描左子树
         p=p->Lchild;
         else
            if (x>p->element)//如果大于该节点的权值,扫描右子树
         p=p->Rchild;//这边要注意一定要有else,笔者这边曾经犯错~~,否则满足了x<p->element之后的值又满足了x>p->element~~
          else
         {
            printf("该数已经存在!\n");//否则二叉搜索树已经存在该值,不需要再插入
            return;
          }
    }
               if (x<q->element)//因为前面是while(q),即运行结果是当q为NULL时,此时最后一个非空节点为q
              q->Lchild=r;
               else
                 q->Rchild=r;

}
int find(tree *h,int x)//该函数的目的是看看x是否在二叉搜索树中,如果在返回1,反之返回0
{

    node *p=h->root;
    while(p)
    {

        if (x<p->element)
            p=p->Lchild;
        if (x>p->element)
            p=p->Rchild;
        else
            return 1;
    }
    return 0;

}

 void Remove(tree *h,int x)//该函数的目的是在二叉搜索树中删除权值为x的值
                          //删除方法是首先通过搜索找到该节点(如果该节点不存在则提示),分两种情况
                          //1,若该节点有两棵子树,用中序遍历的后续节点来代替该节点,再用2来删除后续节点(因为中序遍历一定是遍历该节点的右子树的左子树一直到底,即一定最多只有一棵子树)
                          //2,若该节点最多只有一棵子树(或者需要删除的后续节点只有一棵子树),那么如果左子树非空用左孩子代替
                          //如果右子树非空,那么用右孩子代替,注意删除根节点的特殊情况
{
     node *p=h->root,*r,*s,*q,*c;
     while (p&&p->element!=x)
     {
         q=p;
         if (x<p->element)
          p=p->Lchild;
          else
         if (x>p->element)
          p=p->Rchild;
     }
    if (!p)//如果直接到最后了,说明搜索树中不存在该值
    {
    printf("没有找到该值\n");
    return;
    }
    if (p->Lchild&&p->Rchild)//如果左子树和右子树都存在
    {
      s=p->Rchild;//中序遍历根节点后是右子树(因为p是要删除的节点,所以不能动)
      r=p;
      while (s->Lchild)//遍历这个时右子树先扫描右子树的左子树(这个应该算是中序遍历的内容吧~~)
      {
          r=s;
          s=s->Lchild;
      }
      p->element=s->element;//如何替换:1权值替换2接下去的指向替换(此时p已经是后继节点了),这个有点坑,p=s其实是指向的变换,并不是内容的交换
      p=s;
      q=r;//3父节点指向替换
    }
    if (p->Lchild)
    c=p->Lchild;
    else
        c=p->Rchild;
    if (p==h->root) h->root=c;//如果删除根节点,那么直接用存在的子孩子代替
     else
        if (p==q->Lchild) q->Lchild=c;
        else
            q->Rchild=c;
}
void PreOrd(node *a)
{

    if (a)
    {

        printf("%d ",a->element);
        PreOrd(a->Lchild);
        PreOrd(a->Rchild);

    }
}
   int main()
   {
      tree s;
      node *start;
      int t;
      creat(&s);
      Insert(&s,4);//验证Insert函数
      Insert(&s,2);
      Insert(&s,6);
      Insert(&s,1);
      Insert(&s,3);
      Insert(&s,5);
      Insert(&s,7);
      printf("搜索树已建成!先序遍历结果为:");
      PreOrd(s.root);
      printf("\n");
      printf("请输入需要搜索的数\n");
      scanf("%d",&t);//验证find函数
      if (find(&s,t))
        printf("%d在搜索树中\n",t);
      else
        printf("%d不在搜索树中\n",t);
        printf("请输入需要删除的数\n");
        scanf("%d",&t);
        Remove(&s,t);
        printf("修改过后的搜素树的前序遍历为:");
        PreOrd(s.root);
        printf("\n");
        return 0;
   }
//思考,原来我认为这个Insert是需要有返回值的,即一旦是根节点要返回根节点地址,后来我发现并不需要,因为s->root永远都是指的根节点,就算后来有删除操作,

//也会妥善处理根节点的问题,所以不需要返回值~~




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值