zoukankan      html  css  js  c++  java
  • 二叉排序树(Binary Sort Tree)

    参考文章:http://blog.csdn.net/ns_code/article/details/19823463

    不过博主的使用第一种方法操作后的树已经不是二叉排序树了,值得深思!!

    #include "stdio.h"
    #include "stdlib.h"
    
    //二叉链表结点 
    typedef struct Node{
        int data;
        struct Node *lchild,*rchild;
    }Node,*BSTree;
    
    
    /*
    在指针pTree所指的二叉排序树中递归查找关键字为key的元素,
    若查找成功,则返回ture,并将 查找到的数据对应的节点指针 保存在p中,
    否则返回0,并将 查找路径上访问的最后一个节点指针 保存在p中。
    这里的参数f指向每次递归遍历的子树的根节点的父节点,即始终是参数pTree的父节点, 
    它的初始值为NULL,其目的是跟踪查找路径上访问的当前节点的父节点(即上一个访问节点)
    该函数用来被后面的插入结点函数调用。
    */
    int search_Node(BSTree pTree,int key,BSTree f,BSTree &p)
    {
        if(!pTree){
            p = f;
            return 0;
        }else if(key == pTree->data){
            p = pTree;
            return 1;
        }else if(key > pTree->data){
            search_Node(pTree->rchild,key,pTree,p);
        }else{
            search_Node(pTree->lchild,key,pTree,p);
        }
        
    }
    
    
    /*
    往二叉排序树种插入结点 
    当在pTree所指向的二叉排序树中查找不到关键字为key的数据元素时,
    将其插入该二叉排序树,并返回1,否则返回0。
    树空时插入会改变根节点的值,因此要传入引用。
    
     */
    int insertNode(BSTree &pTree,int key)
    {
        BSTree p;
        if(!search_Node(pTree,key,NULL,p)){
            
            BSTree pNew = (BSTree)malloc(sizeof(Node));  //产生新元素的结点 
            pNew->lchild = pNew->rchild = NULL;
            pNew->data = key;
            
            if(!p){
                pTree = pNew;            //如何树空,直接将pNew置为根节点 
            }else{
                if(key > p->data){
                    p->rchild = pNew;        //作为右孩子插入p的右边 
                }else{
                    p->lchild = pNew;        //作为左孩子插入p的左边 
                }        
            }
            return 1;
        }else
            return 0;
        
    }
    
    
    //创建二叉排序树 
    BSTree create_BSTree(int *arr,int num)
    {
        BSTree pTree = NULL;
        int i;
        for(i=0;i<num;i++)
            insertNode(pTree,arr[i]);
        return pTree;
        
    }
    
    //递归中序遍历二叉树,得到元素从小到大的有序排列 
    void InorderTraverse(BSTree pTree)
    {
        if(pTree){        
            InorderTraverse(pTree->lchild);
            printf("%d ",pTree->data);
            InorderTraverse(pTree->rchild);    
        }
    }
    
    //修改左子树的方法删除结点 
    int delete_Node1(BSTree &p)
    {
        BSTree q,s;
        if(!p->lchild){                  //左子树为空,只需重新接上右子树    
            q = p;
            p = p->rchild;
            free(q);
        }else if(!p->rchild){        //右子树为空,只需重新接上左子树
            q = p;
            p = p->lchild;
            free(q);
        }else{                        //如果左右子树都不为空
                                    //我们这里采取修改左子树的方法,也可以修改右子树,方法类似
            q = p;
            s = p->lchild;            //取待删节点的左节点
            while(s->rchild){        //一直向右,最终s为待删节点的前驱节点。
                                    //如果将各节点元素按从小到大顺序排列成一个序列,
                                    //则某节点的前驱节点即为序列中该节点的前面一个节点
                q = s;
                s = s->rchild;
            }
            //用s来替换待删节点p
            p->data = s->data;
            //根据情况,将s的左子树重接到q上
            if(p != q){
                q->rchild = s->lchild;
            }else{
                q->lchild = s->lchild;
            }    
            free(s); 
        }
        return 1;
    }
    
    //修改右子树的方法删除结点
    int delete_Node2(BSTree &p)
    {
        BSTree q,s;
        if(!p->lchild){                //左子树为空,只需重新接上右子树
            q = p;
            p = p->rchild;
            free(q);
        }else if(!p->rchild){        //右子树为空,只需重新接上左子树
            q = p;
            p = p->lchild;
            free(q);
        }else{
            q = p;
            s = p->rchild;
            while(s->lchild){
                q = s;
                s = s->lchild; 
            }
            //用s来替换待删节点p
            p->data = s->data;
            //根据情况,将s的左子树重接到q上
            if(p != q){
                q->lchild = s->rchild;
            }else{
                q->rchild = s->rchild;
            }
            free(s);
        }
        return 1;
    } 
    
    //删除结点 
    int delete_BSTree(BSTree &pTree,int key)
    {
        if(!pTree){            //不存在关键字为key的结点 
            return 0;
        }else{
            if(key == pTree->data){
            //    return delete_Node1(pTree);
                return delete_Node2(pTree);
            }else if(key > pTree->data){
                return delete_BSTree(pTree->rchild,key);
            }else{
                return delete_BSTree(pTree->lchild,key);
            }
        }
    }
    
    
    int main()
    {
        BSTree pTree;
        int i,num,flag;
        printf("请输入节点的个数:");
        scanf("%d",&num);
    //    printf("%d
    ",num);
        
        int *arr = (int *)malloc( num * sizeof(int));
        for(i=0;i<num;i++)
            scanf("%d",arr+i);
        
        pTree = create_BSTree(arr,num);
        printf("中序遍历该二叉排序树的结果:");  
        InorderTraverse(pTree);printf("
    "); 
        
        printf("请输入要删除的结点:");
        scanf("%d",&num);
        flag = delete_BSTree(pTree,num);
        if(flag){
            printf("删除成功!
    ");
        }else{
            printf("删除失败!
    ");
        }
        printf("中序遍历该二叉排序树的结果:");
        InorderTraverse(pTree);printf("
    "); 
    
    
        return 0;
    }
    View Code

    敲敲代码有益身心,嘎嘎

    参考书籍:《大话数据结构》

  • 相关阅读:
    NRF24L01 使用小结/自动应答/通道地址
    nRF24L01单片机通信的总结--看了就会用了
    彻底搞懂状态机(一段式、两段式、三段式)
    面向硬件的设计思维--时钟是电路的实际控制者
    组合逻辑电路-----竞争与冒险现象
    Win7、Win8、Win10系统USB-Blaster驱动程序无法安装的解决办法
    从DTFT到DFS,从DFS到DFT,从DFT到FFT,从一维到二维
    离散傅里叶级数DFS几个主要的特性
    离散傅里叶级数DFS
    Ubuntu12.10下Python(cx_Oracle)访问Oracle解决方案
  • 原文地址:https://www.cnblogs.com/heyijing/p/4826472.html
Copyright © 2011-2022 走看看