zoukankan      html  css  js  c++  java
  • C算法学习笔记(2)-二叉查找树

    本文原始地址:C算法学习笔记(2)-二叉查找树


    查找操作

    若根结点的关键字值等于查找的关键字,成功。
    否则,若小于根结点的关键字值,递归查左子树。
    若大于根结点的关键字值,递归查右子树。
    若子树为空,查找不成功。

    /*
     //二叉树查找算法
     //T 二叉树
     //x 要查找的值
     */
    BiTree BSTSearch(BiTree T,int x)
    {
        BiTreeNode *p;
        if (T != NULL)
        {
            p = T;
            while (p != NULL)
            {
                if (p->data == x)//如果该结点就是我们想要的
                {
                    return p;
                }else if(x > p->data)//如果查找的值是该结点右子树
                {
                    p = p->rchild;
                }else//如果查找的值是该结点左子树
                {
                    p = p->lchild;
                }
            }
        }
        return NULL;
    }


    插入操作

    首先执行查找算法,找出被插结点的父亲结点。
    判断被插结点是其父亲结点的左、右儿子。将被插结点作为叶子结点插入。
    若二叉树为空。则首先单独生成根结点。
    注意:新插入的结点总是叶子结点。

    /*
     //二叉树插入操作
     //T 二叉树
     //x 要插入的值
     */
    int BSTInsert(BiTree *T,int x)
    {
        BiTreeNode *p = NULL;//把x组装成一个只有根结点的树
        BiTreeNode *cur = NULL;//纪录当前遍历的结点
        BiTreeNode *parent = NULL;//纪录上一次遍历的结点,最后一个值为我们需要插入的结点位置
        cur = *T;
        while (cur != NULL)
        {
            if (cur->data == x)//插入操作如果数值已存在,插入失败
            {
                return 0;
            }
            parent = cur;//将到该结点子树遍历,纪录下该结点,该循环最终输出值
            if (x < cur->data)//到该结点左子树继续遍历
            {
                cur = cur->lchild;
            }else//到该结点右子树继续遍历
            {
                cur = cur->rchild;
            }
        }
        //申请内存空间
        p = (BiTreeNode *)malloc(sizeof(BiTreeNode));
        if (!p)//内存空间申请失败,内存不够用了,终止程序
        {
            exit(-1);
        }
        //初始化p结点
        p->data = x;
        p->lchild = NULL;
        p->rchild = NULL;
        
        if (!parent)
        {
            *T = p;//这本来就是棵空树,p将会作为根结点
        }else if(x < parent->data)
        {
            parent->lchild = p;
        }else
        {
            parent->rchild = p;
        }
        return 1;//插入成功
    }



    删除操作

    1.若*p结点为叶子结点,即PL(左子树)和PR(右子树)均为空树。由于删去叶子结点不破坏整棵树的结构,则只需修改其双亲结点的指针即可。
    2.若*p结点只有左子树PL或右子树PR,此时只要令PL或PR直接成为其双亲结点*f的左子树(当*p是左子树)或右子树(当*p是右子树)即可,作此修改也不破坏二叉排序树的特性。
    3.若*p结点的左子树和右子树均不空。在删去*p之后,为保持其它元素之间的相对位置不变,可按中序遍历保持有序进行调整,可以有两种做法:
    其一是令*p的左子树为*f的左/右(依*p是*f的左子树还是右子树而定)子树,*s为*p左子树的最右下的结点,而*p的右子树为*s的右子树;
    其二是令*p的直接前驱(或直接后继)替代*p,然后再从二叉排序树中删去它的直接前驱(或直接后继)-即让*f的左子树(如果有的话)成为*p左子树的最左下结点(如果有的话),再让*f成为*p的左右结点的父结点。

     

    /*
     //删除结点
     //删除的结点s
     //原则:保持二叉树性质不变-根结点的值大于左子树的值小于右子树的值...
     */
    void DeleteNode(BiTree *s)
    {
        if (!s) return;
        BiTreeNode *q = NULL;//中间量,纪录旧的的s结点数据
        BiTreeNode *x = NULL;
        BiTreeNode *y = NULL;
        
        if(!(*s)->rchild)//如果右子树不存在
        {
            q = (*s);
            (*s) = (*s)->lchild;
            free(q);
        }else if(!(*s)->lchild)//如果左子树不存在
        {
            q = (*s);
            (*s) = (*s)->rchild;
        }else//如果左右都存在的话,令*p的直接前驱(或直接后继)替代*p,然后再从二叉排序树中删去它的直接前驱(或直接后继)-即让*f的左子树(如果有的话)成为*p左子树的最左下结点(如果有的话),再让*f成为*p的左右结点的父结点。
        {
            x = (*s);
            y = (*s)->lchild;
            while (y->rchild)//查找s的直接前驱结点,y为s的直接前驱结点,x为y的双亲结点
            {
                x = y;
                y = y->lchild;
            }
            (*s)->data = y->data;//结点s被y取代
            if (x != (*s))//如果结点s的左孩子结点不存在右子树
            {
                x->rchild = y->lchild;//使y的左子树成为x的右子树
            }else
            {
                x->lchild = y->lchild;
            }
            free(y);
        }
    }
    
    
    /*
     //在二叉树中查找关键字为x的结点,并删除,删除成功返回1,否则返回0
     //T 二叉树
     //x 关键字
     */
    int BSTDelete(BiTree *T,int x)
    {
        if (!*T) return 0;
        if (x == (*T)->data)
        {
            DeleteNode(T);
        }else if (x < (*T)->data)
        {
            BSTDelete(&(*T)->lchild,x);
        }else
        {
            BSTDelete(&(*T)->rchild,x);
        }
        return 1;
    }

    附:中序遍历

    //中序遍历
    void InOrderTraverse(BiTree T)
    {
        if (T)
        {
            InOrderTraverse(T->lchild);
            printf("%4d",T->data);
            InOrderTraverse(T->rchild);
        }
    }


    视频地址:BST:二叉查找树

    关于二叉查找树

  • 相关阅读:
    物联网习题总结
    orm.TextField undefined (type orm.Ormer has no field or method TextField)
    中级软件设计师下午试题(百度文库 )
    34-Digit factorials
    解决[INS-35075] 已存在具有指定标识符的数据库实例
    PE10 Summation of primes
    构建之发阅读笔记02
    软件工程概论第十二周学习进度表
    四则运算2(改进版)
    构建之法阅读笔记01
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3063596.html
Copyright © 2011-2022 走看看