第七章:查找之二叉排序树

#include <stdio.h>
#include <string.h>
#define N 100
typedef struct 
{
    int key;
    int others;
}Data;
typedef struct LNode
{
    Data data;//数据域
    LNode *l,*r;  //指针域
}LNode,*LinkList; //每个结点的类型;
LinkList root;

//void Creat(LinkList &L)
//{
//    L=new LNode;
//    L->l=L->r=NULL;
//    L->data.key=0;
//    printf("二叉排序树初始化完毕!\n");
//}
LinkList Search(LinkList p,int key) //在二叉排序中寻找关键字为key的结点,并返回结点指针。
{
    if(!p || p->data.key==key) return p;
    else
        if(p->data.key>key)
            return Search(p->l,key); //这里只会传过去形式参数!!  不需要另设参数来进行什么比较。
        else
            return Search(p->r,key);
}

void Insert(LinkList &L,int key)
{
    //向二叉排序中插入某置为 key 的元素结点。
    if(!L) 
    {
        //  L是一个指针! 指向一片空的地址。  现在可以直接给它new一片空间来让它进行存储即可。
        // 试验下这样可以成功么!     ----------------可以成功!
        L=new LNode;
        L->data.key=key;
        L->l=L->r=NULL;
    }
    else
    {
        if(key<L->data.key)
            Insert(L->l,key);
        else
             Insert(L->r,key);
    }
}

void Creat(LinkList &L)
{
    //利用插入函数 Insert 建立二叉排序树!
    printf("现在我们要建立一个二叉排序树,请输入你想要输入的结点个数:\n");
    int n;scanf("%d",&n);
    while(n--)
    {
        int key;scanf("%d",&key);
        Insert(L,key);
    }
}
void Print(LinkList L)
{
    //中序遍历打印二叉排序树!
    if(L)
    {
        Print(L->l);
        printf("%d  ",L->data.key);
        Print(L->r);
    }
}

void Delete(LinkList &L,int key)
{
    //删除关键字为key的结点;
    /*
    算法思想:
    先找到值为key的结点,p指向它,同时pre记录下它的父节点。

    看结点p是四种情况下的哪一种,使用if else 语句进行处理。
    */
    int t;//标志变量,记录p为pre的右还是左孩子结点。
    LinkList pre=NULL,p=NULL;pre=L;
    if(key==L->data.key)
        p=L;   // 当需要删除的结点为根节点的时候;
    else if(key > L->data.key)
    {    p=L->r;t=2;}    
    else
    {    p=L->l;t=1;}
    if(!p)
        printf("输入错误,没有值为%d的结点!\n",key);
    else
    {
        while(p)
        {
            if(key==p->data.key)
                break;
            else if(key > p->data.key)
            {    pre=p;p=p->r;t=2;}
            else
            {    pre=p;p=p->l;t=1;}
        }
        if(!p) //如果p为空,证明查找不成功,没有值为key的结点!
            printf("输入错误,没有值为%d的结点!\n",key);
        else
        {
            //已经找到值为key的结点,现在判别4种情况,再做下一步变化。
            //(这是pre指向的是p的前一个结点!)
            if(!p->l && !p->r)        //左右都空;
            {    
                if(t==2)    pre->r=NULL;
                else    pre->l=NULL;
                delete p;
            }
            else if(!p->l && p->r) //左空右不空;
            {
                if(t==2)
                    pre->r=p->r;
                else
                    pre->l=p->r;
                delete p;
            }
            else if(!p->r && p->l) //右空,左不空;
            {
                if(t==2)
                    pre->r=p->l;
                else 
                    pre->l=p->l;
                delete p;
            }
            else //左右都不空!  找到左子树的最大的节点,即中序遍历的最后一个结点即可。
            {
                LinkList e=p->l,m=p;
                while(e->r)
                {    m=e;e=e->r; }
                //  e即是最小的结点。  m是其前驱结点;
                //这里简单处理一下,将e的数据域赋值到p中即可,并且释放e;
                p->data=e->data;
                if(m!=p)
                    m->r=NULL;
                else 
                    m->l=NULL;
                delete e;
            }
        }
    }

}
int main()
{
    Creat(root);
    Print(root);printf("\n");
    Delete(root,53);
    Print(root);printf("\n");
    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值