• 二叉排序树


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

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

    所有的代码如下:

    #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)左右子树都不为空

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

  • 相关阅读:
    [solution]xdebug正确配置,但不显示错误信息
    SIGCHLD信号
    sigsuspend
    信号引起的竞态
    智力面试题
    可重入和不可重入
    信号—信号处理函数(捕捉)
    PCB信号集
    信号产生的原因:
    信号初步
  • 原文地址:https://www.cnblogs.com/qian-yi/p/12797064.html
Copyright © 2020-2023  润新知