二叉排序树

  二叉排序树:插入、删除、查找性能都不错,构建起来也不是很复杂,性能还很稳定的数据结构。

  数组:适合查找操作     链表:适合插入和删除操作

所有的代码如下:

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

typedef struct BiTNode{
    int data; //结点数据
    struct BiTNode *lchild,*rchild;  //左右子树 
}BiTNode,*BiTree;

//二叉排序树的添加
void insertNode(BiTree &T,int key)
{
    if(T==NULL)  //如果二叉排序树为空 
    { 
        T=(BiTNode*)malloc(sizeof(BiTNode));
        T->data=key;
        T->lchild=NULL;
        T->rchild=NULL;
    }
    else if(key<T->data)
    {
        insertNode(T->lchild,key);  //往左边走 
    }
    else if(key>T->data)
    {
        insertNode(T->rchild,key); //往右边走 
    }
    else
    {
        printf("已有该结点值得存在,无法插入
");
    }
}

//生成二叉排序树
void createBiTree(BiTree &T,int *a,int n)
{
    int i=0; 
    while(i<n)
    {
        insertNode(T,a[i]);
        i++;
    }    
}

//二叉树的查找操作
int searchBiTree(BiTree T,int key)
{
    if(T==NULL)
    {
        return -1;
    }
    else if(key<T->data)
    {
        searchBiTree(T->lchild,key);  //在左子树查找 
    }
    else if(key>T->data)
    {
        searchBiTree(T->rchild,key); //在右子树查找 
    }
    else  //key==T->rchild->data 
    {
        return 1;  //查找成功 
    } 
}

//二叉排序树的删除操作
void deleteNode(BiTree &T,int key)
{
    //先要找到值为key的结点
    if(T==NULL)
    {
        printf("无法删除该操作
");
    }
    else if(key<T->data)
    {
        deleteNode(T->lchild,key);
    }
    else if(key>T->data)
    {
        deleteNode(T->rchild,key);
    }
    else  //key==T>data  找到了该结点 
    {
        BiTree m,n;//指向结点的指针 
        if(T->lchild==NULL) //只有右子树 
        {
            m=T;//赋值该结点,避免指针找不到了,造成内存泄漏
            T=T->rchild; //指针指向的位置发生改变 
            free(m); //释放该结点 
        }
        else if(T->rchild==NULL) //只有左子树 
        {
            m=T;//赋值该结点,避免指针找不到了,造成内存泄漏
            T=T->lchild; //指针指向的位置发生改变 
            free(m); //释放该结点 
        }
        else  //既有左子树也有右子树 
        {
            m=T;
            n=T->lchild;
            while(n->rchild)//找到T结点左子树的最大值 
            {
                m=n;          //m是n的双亲   n是T结点左子树的最大值 
                n=n->rchild;
            }
            
            T->data=n->data;  //我们不用释放该结点,我们是释放的是T结点左子树的最大值
            
            if(m!=T)  //当n是T的左子树时,m==T
            {
                m->rchild=n->lchild;
            }
            else
            {
                m->lchild=n->lchild;
            }
            free(n);
        }
    }
} 


//二叉排序树的中序遍历
void printfSort(BiTree T)
{
    if(T)  //如果不是空树 
    {
        printfSort(T->lchild);
        printf("%d ",T->data);
        printfSort(T->rchild);
    }
}

int main()
{
    BiTree T=NULL; //一开始的结点为空 
    int number;
    printf("请输入你要进行排序数的个数
");
    scanf("%d",&number);
    int a[number];
    
    printf("请依次输入序列的值
");  //  5  4  1  3  2  10  8  7  15  6
    for(int i=0;i<number;i++)
    {
        scanf("%d",&a[i]);
    }
    
    createBiTree(T,a,number);  //数组生成二叉排序树
    
    printf("结束操作---------0
");
    printf("查找操作---------1
");
    printf("插入操作---------2
");
    printf("删除操作---------3
");
    printf("打印操作---------4
");
    int n,k;  //n是指令  k是数值 
    printf("请输入指令:");
    scanf("%d",&n);
    
    while(n!=0)
    {
        switch(n)
        {
            case 0:
                break;
            case 1:  //查找操作 
                printf("请输入你要查找的数值:");
                scanf("%d",&k);
                if(searchBiTree(T,k)>0)
                {
                    printf("查找成功
");
                }
                else
                {
                    printf("查找失败
");
                }
                break; 
            case 2:   //插入操作
                printf("请输入你要插入的数值:");
                scanf("%d",&k);
                insertNode(T,k);
                break;
            case 3:   //删除操作
                printf("请输入你要删除的数值:");
                scanf("%d",&k);
                deleteNode(T,k);
                break;
            case 4:  //打印操作
                printfSort(T);
                printf("
");
                break;
            default:
                printf("你输入的指令不正确
");
                
        }
        printf("请重新输入指令:");
        scanf("%d",&n);
    }
    free(T);
    return 0;
}

  该程序功能已基本实现,可以正常运行

遗留的问题:删除节点操作考虑三种情况 (1)左子树为空  (2)右子树为空  (3)左右子树都不为空

但是为什么没有考虑左右子树都为空的情况,但是删除操作还是可以正常进行删除没有左右子树的结点,这是我疑惑的地方!

原文地址:https://www.cnblogs.com/qian-yi/p/12797064.html