二叉搜索树的学习笔记(有解释)

本文介绍了一种二叉搜索树的实现方法,包括查找、插入、删除等基本操作,并提供了详细的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include<iostream>
#include<cstdio>
using namespace std;
#include<stdlib.h>
#include<malloc.h>
typedef int Elemtype;
typedef struct BiTreenode
{
        Elemtype data;
        struct BiTreenode *Lchild;
        struct BiTreenode *Rchild;
}*BiT,BiTree;

//1.查找元素,有Find递归方式和Find2非递归方式两种
Elemtype *Find(BiT BST,Elemtype x)
{
        if(BST==NULL){return NULL;}
        else
        {
                if(x==BST->data)
                {
                        return &(BST->data);
                }
                else if(x<BST->data)
                {
                        return  Find(BST->Lchild,x);//向左子树进行搜索
                }
                else
                {
                        return Find(BST->Rchild,x);//向右子树进行搜索
                }
        }
}

Elemtype *Find1(BiT BST,Elemtype x)
{
        while(BST!=NULL)
        {

                if(x==BST->data){return &(BST->data);}
                else if(x<BST->data)
                {
                        BST=BST->Lchild;
                }
                else{BST=BST->Rchild;}
        }
        return NULL;
}

//2.数据的更新,与查找算法相同,只需要在返回之前将找到的值替换再返回即可再次省略;
//3.在二叉搜索树中插入元素x;(有递归和非递归两种)
void Insert(BiT *BST,Elemtype x)//用指针的指针是为了改变插入的树的父节点的左/右孩子的指针的值,(因为函数的形参特性)
{
     if(*BST==NULL)
     {
             BiT p=(BiT)malloc(sizeof(BiTree));
             p->data=x;
             *BST=p;
             p->Lchild=NULL;
             p->Rchild=NULL;
             return;
     }
     else
     {
             if(x<(*BST)->data)
             {
                Insert(&((*BST)->Lchild),x);
             }
             else
             {
                Insert(&((*BST)->Rchild),x);
             }
     }
     return;
}
//非递归
void Insert2(BiT *BST,Elemtype x)
{
        BiT p;
        BiT t=*BST,parent=NULL;
        while(t!=NULL)
        {
                parent=t;
                if(x<t->data)
                {
                        t=t->Lchild;
                }
                else{t=t->Rchild;}
        }//循环之后parent存储的是带插入位置的双亲节点;
        p=(BiT)malloc(sizeof(BiTree));
        p->data=x;
        p->Lchild=p->Rchild=NULL;
        if(parent==NULL)
        {
                *BST=p;
        }
        else
        {
                if(x<parent->data)
                {
                        parent->Lchild=p;
                }
                else
                  {
                          parent->Rchild=p;
                  }
        }
        return;

}

//4.删除
//a.删除叶子节点,只要将其双亲节点链接到它的指针置空即可
//b.删除单支节点,只要将其后继指针链接到它所在的链接位置即可;
//c.删除双支节点,一般采用的方法是首先把它的中序前驱节点的值赋给该节点的值域
//然后再删除它的中序前驱结点,若它的中序前驱节点还是双支节点,继续对其做同样的操作
//若是叶子结点或单支节点则做对应的操作,若是根节点则结束
int Delete(BiT*BST,Elemtype x)
{
        BiT temp;
        temp=*BST;
        if(*BST==NULL)
        {
                return 0;
        }
        if( x < (*BST)->data )
        {
                return Delete( &( (*BST)->Lchild ),x);
        }
        if(x > (*BST)->data )
        {
                return Delete( &( (*BST)->Rchild ),x);
        }
        if( (*BST)->Lchild==NULL )//由于上面的if已经判断了x的大小,因此这里是一定x==(*BST)->data的,此时做字数为空,将右子树作为整个树并返回1
        {
                *BST=(*BST)->Rchild;
                free(temp);
                return 1;
        }
        else if( (*BST)->Rchild==NULL )//右子树为空,将左子树作为整个树返回1
        {
                *BST=(*BST)->Lchild;
                free(temp);
                return 1;
        }
        else
        {
                if( (*BST)->Lchild->Rchild==NULL )
                {
                        (*BST)->data=(*BST)->Lchild->data;
                        return Delete( &(*BST)->Lchild,(*BST)->data );
                }
                else
                {
                        BiT p1=*BST,p2=p1->Lchild;
                        while(p2->Rchild!=NULL)
                        {
                                p1=p2;
                                p2=p1->Rchild;
                        }
                        (*BST)->data=p2->data;
                        return Delete(&(p1->Rchild),p2->data);
                }
        }
}

//创建搜索二叉树
void create(BiT *BST,Elemtype a[],int n)
{
    int i;
    *BST=NULL;
    for(i=0;i<n;i++)
    {
            Insert(BST,a[i]);
    }
}

//输出二叉树(即可看出二叉树的表示法则)
void print(BiT PT)
{
        if(PT!=NULL)
        {
                printf("%d ",PT->data);
                if(PT->Lchild!=NULL||PT->Rchild!=NULL)
                {
                        printf("(");
                        print(PT->Lchild);
                        if(PT->Rchild!=NULL){printf(",");}
                        print(PT->Rchild);
                        printf(")");
                }

        }
}
//中序遍历输出
void midprint(BiT PT)
{
        if(PT!=NULL)
        {
                midprint(PT->Lchild);
                printf("%d ",PT->data);
                midprint(PT->Rchild);
        }
}

//清空二叉树使之变为一颗空树
void BTclear(BiT *BST)//为了不再多开一个临时指针我们采用从叶子节点开始删除,即从尾往上删除提高效率
{
        if(*BST!=NULL)
        {
                BTclear(&((*BST)->Lchild));//删除左子树;
                BTclear(&((*BST)->Rchild));//删除右子树;
                free(*BST);//释放根节点;
                *BST=NULL;//置根节点为空防止成为野指针;
        }
}

//主函数
int main()
{
   int x,*px;
   Elemtype a[10]={30,50,20,40,25,70,54,23,80,92};
   BiT BST=NULL;
   create(&BST,a,10);

   printf("建立的二叉搜索树的按定义表示形式为:\n");
   print(BST);
   printf("\n");

   printf("the mid order:\n");
   midprint(BST);
   printf("\n");

   printf("pleas input the element which is wanted: ");
   scanf(" %d",&x);//空格可以忽略前面的其他字符防止出错;
   px=Find(BST,x);
   if(px!=NULL)
   {
           printf("succeed in finding and we get the value is %d\n",*px);
   }
   else
   {
           printf("FAILED in fingding x!\n");
   }

   printf("please input the element inserted: ");
   scanf(" %d",&x);
   Insert(&BST,x);

   printf("please input the element inserted: ");
   scanf(" %d",&x);
   Insert(&BST,x);

   printf("please input the element inserted: ");
   scanf(" %d",&x);
   Insert(&BST,x);

   printf("After the operation above and do the midprint:\n");
   midprint(BST);
   printf("\n");

   printf("please input the element which will be deleted: ");
   scanf(" %d",&x);
   if(Delete(&(BST),x))
   {
           printf("1\n");
   }
   else{printf("0\n");}

   printf("after the operation:\n");
   midprint(BST);
   printf("\n");

   BTclear(&(BST));

   return 0;

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值