二叉排序树

二叉排序树是一种特殊的数据结构,其特点包括左子树所有节点值小于根节点,右子树所有节点值大于根节点,且左右子树皆为二叉排序树。在查找操作中,最坏情况下查找次数为o(n),而最佳情况为o(log n)。通过中序遍历,二叉排序树能输出有序序列,适用于树排序,具有o(n*log n)的排序复杂度。

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

特点:

1)左子树非空则左子树所有节点的值小于根节点

2)右子树非空则右子树所有节点的值大于根节点

3)左右子树都为二叉排序树

查找次数等于树高,最坏情况为o(n),最好为o(log n)

以中序遍历输出则为有序序列,也可以称为树排序,排序复杂度o(n*log n)

# include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
typedef int datatype;
struct bsnode
{
    datatype data;
    bsnode *l,*r;
    bsnode(){l=r=NULL;}
};
bsnode* Insert(bsnode *t,datatype x)
{
    bsnode *p=t,*f=NULL;//f为表示下一个点的父节点
    while(p)
    {
        if(p->data==x) return t ; //若该值已在树中出现,就不必再插入
        f=p;
        if(x<p->data)  p=p->l; //比根小就往左边走
        else p=p->r;//否则往右边
    }
    p=new bsnode();
    p->data=x;
    if(f==NULL) return p;
    if(x<f->data)  f->l=p;
    else f->r=p;
    return t;
}
bsnode *create() //建立二叉排序树
{
    datatype x;
    bsnode *root=NULL;
    cin>>x;
    while(x!=-1)
    {
        root=Insert(root,x);
        cin>>x;
    }
    return root;
}
void inorder(bsnode *t) //中序遍历输出
{
    if(t==NULL) return ;
    inorder(t->l);
    cout<<t->data<<' ';
    inorder(t->r);
}
bsnode * FindX(bsnode *t,datatype x) //递归查找值为x节点
{
    if(t==NULL||t->data==x) return t;
    if(x<t->data) return FindX(t->l,x);
    return FindX(t->r,x);
}
void FindXbyloop(bsnode *t,bsnode **f,bsnode **p,datatype x) //非递归查找值x的节点和x父节点
{
    *p=t;
    *f=NULL;
    while(*p)
    {
        if((*p) -> data==x)  return ;
        *f=*p;
        if(x<(*p)->data)  *p=(*p)->l;
        else *p = (*p)->r;
    }
}
bsnode *DeleteX(bsnode *t,datatype x) //二叉排序树删除节点
{
    bsnode *p,*orderpre,*f,*q;
    FindXbyloop(t,&f,&p,x);//找到待删除的节点和父亲
    q=p;//保存待删点
    if(p==NULL) return t;
    if(p->l==NULL&&p->r==NULL) //删除的为叶子节点
    {
        if(f==NULL) t=NULL; //若只有根节点,返回空树
        else if(f->l->data==x) f->l=NULL; // 若左儿子等于x,父节点左儿子指向为空
                 else f->r=NULL; //否则右儿子为空
        free(q);
    }
   else if(p->l==NULL) //删除一度节点且删除节点左儿子为空
   {
       if(f==NULL) t=p->r; //若该节点为根,左儿子右儿子作为根
       else if(f->l->data==x)  f->l=p->r; // 节点位于中间,父节点的左儿子为删除节点,使父节点左儿子指向删除节点的右儿子
               else f->r=p->r; //父节点的右儿子指向删除节点的右儿子
        free(q);
   }
   else if(p->r==NULL) //删除一度节点且右儿子为空
   {
       if(f==NULL)  t=p->l;
       else if(f->l->data==x) f->l=p->l;
                else f->r=p->l;
        free(q);
   }
   else //删除二度节点(把删除节点右子树的前趋替换删除节点)
   {
       orderpre = p->r;
       while(orderpre->l) orderpre=orderpre->l;//找到右子树的前趋
       orderpre->l=p->l;//使得删除节点的左子树作为右子树前趋节点的左左子树
       if(f==NULL)  t=p->r; //如果被删除的是根,被删除节点的右儿子作为根
       else if(f->l->data==x) f->l=p->r; //节点处于中间,父节点的左儿子为删树节点,则把删除节点的右儿子作为父节点的左儿子
               else f->r=p->r;
        free(q);
   }
   return t;
}
int main()
{
    datatype  x;
    int n = 5;
    bsnode *root,*p,*f;
    root=create();
    inorder(root);
    cout<<endl;
   /* cin>>x;
    p=FindX(root,x);
    if(p) cout<<p->data<<endl;
    else cout<<"不存在"<<endl;*/
  /*  FindXbyloop(root,&f,&p,x);
    if(p!=NULL) cout<<f->data<<"   "<<p->data<<endl;*/
   while(n)
   {
       cin>>x;
       root=DeleteX(root,x);
       inorder(root);
       cout<<endl;
   }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值