二叉搜索树的建立 添加结点 删除结点

BST_t* create()
{
    return calloc(1, sizeof(BST_t));
}

void insert(BST_t* tree, char key)
{
    TreeNode_t* prev = NULL;
    TreeNode_t* curr = tree->root;

    //查找插入的位置 那个位置肯定是空结点了 其目的不是找到curr而是确定prev
    //因为curr已经是空结点了,无法被赋值,而prev则存在于树的末端
    while (curr != NULL)
    {
        prev = curr;
        if (key < curr->key)
            curr = curr->left;
        else if (key > curr->key)
            curr = curr->right;
        else
            return;
    }

    //小驼峰命名法 好习惯 创建新结点
    TreeNode_t* newNode = calloc(1,sizeof(TreeNode_t));//用calloc好可以直接初始化为NULL,
    //因为tree的左右子树需要判断是否为NULL
    if (newNode == NULL)
    {
        printf("创建结点失败!");
        return;
    }
    newNode->key = key;//给新结点的key成员赋值
    //插入结点 第一次要判断根结点指向 不然一直指向NULL 改变的是curr的指向而不会是root
    //后面添加新结点也是一样的情况,必须拿prev的左右来指向新结点 不能用curr
    if (tree->root == NULL)
        tree->root = newNode;
    else if (key < prev->key)
        prev->left = newNode;
    else
        prev->right = newNode;

    return;
}

void rm(BST_t* tree, char key)
{
    TreeNode_t* prev = NULL;
    TreeNode_t* curr = tree->root;

    //寻找要删除的结点
    while (curr != NULL)
    {
        if (key < curr->key)
        {
            prev = curr;
            curr = curr->left;
        }
        else if (key > curr->key)
        {
            prev = curr;
            curr = curr->right;
        }
        else
            break;
    }
    //没找到的情况
    if (curr == NULL)
    {
        return false;
    }

    //第一种情况:待删除结点度为2。移花接木
    if (curr->left != NULL && curr->right != NULL)
    {
        //度为2的情况 我们准备将右子树中最小的值替换上来 再把本体删掉
        TreeNode_t* parent = curr;
        TreeNode_t* minOfRight = curr->right;
        while (minOfRight->right != NULL)
        {
            parent = minOfRight;
            minOfRight = minOfRight->left;
        }
        //替换 先把右边最小的那个值拷贝过来,再想办法把右边最小值干掉,也就是转嫁成度为0或1的情况
        curr->key = minOfRight->key;
        prev = parent;
        curr = minOfRight;
    }
    // 处理度为0和度为1的情况 child就是要续上的那个结点
    //因为只有度为0和度为1两种情况。左子树存在便续左子树,右子树存在
    //便续右子树(即使它们会是NULL)
    TreeNode_t* child = curr->left != NULL ? curr->left : curr->right;

    if (prev == NULL)//删除整个树的根结点的情况
        tree->root = child;
    //变成child 再干掉原来的child
    else if(curr->key < prev->key)
        prev->left = child;
    else
        prev->right = child;

    free(curr);
}

 

posted @ 2022-02-13 14:36  晓风霜度-  阅读(45)  评论(0)    收藏  举报