二叉树插入删除,遍历

二叉树插入删除,遍历

插入

在这里插入图片描述

在实现插入算法的时候,由于树状结构本身是递归的,因此可以使用递归函数实现插入算法

// 假设 BST 节点存储的数据类型是 int
node *newNode(int data)
{
    // 准备好新节点,并将数据填入其中
    node *new = (node *)malloc(sizeof(node));
    if(new != NULL)
    {
        new->data = data;
        new->lchild = NULL;
        new->rchild = NULL;
    }
    return new;
}

// 将新节点new插入到一棵以 root 为根的 BST 中
// 插入节点后,返回新的 BST 的根
node *bstInsert(node *root, node *new)
{
    // 若此时 BST 为空,则返回 new 使之成为二叉树的根节点
    if(root == NULL)
        return new;

    // 若新节点比根节点小,那么新节点应该插入左子树中
    // 至于插入到左子树的具体什么位置就不用管了,直接递归即可
    if(new->data < root->data)
        root->lchild = bstInsert(root->lchild, new);

    // 若新节点比根节点大,那么新节点应该插入右子树中
    // 至于插入到右子树的具体什么位置就不用管了,直接递归即可
    else if(new->data > root->data)
        root->rchild = bstInsert(root->rchild, new);

    // 若已存在,则不处理
    else
    {
        printf("%d已存在\n", new->data);
        free(new);
    }

    return root;
}

删除节点

假设要删除的节点是x,大体思路如下:

若要删除的节点小于根节点,则递归地在左子树中删除x
若要删除的节点大于根节点,则递归地在右子树中删除x
若要删除的节点恰好就是根节点,则分如下几种情况:
a. 根节点若有左子树,则用左子树中最大的节点max替换根节点,并在左子树中递归删除max
b. 否则,若有右子树,则用右子树中最小的节点min替换根节点,并在右子树中递归删除min
c. 否则,直接删除根节点

以下图为例,假设在一棵二叉树中要删除节点15,在找到节点之后,判断其有左子树,那么就沿着其左子树找到最右下角(最大)的节点19,替换要删除的节点15,然后再将多余的节点19删掉:

在这里插入图片描述

而如果要删除的节点没有左子树,只有右子树,那么情况是完全对称的,如下图所示,假设要删除节点25,由于25没有左子树,因此找到其右子树中最左下角(最小)的节点16,替换要删除的节点25,然后再将多余的节点16删掉:

在这里插入图片描述

// 将数据(以整型为例)data从二叉树中删除
// 并返回删除之后的二叉树的根
node *bstRemove(node *root, int data)
{
    if(root == NULL)
        return NULL;

    // 若data小于根节点,则递归地在左子树中删除它
    if(data < root->data)
        root->lchild = bstRemove(root->lchild, data);

    // 若data小于根节点,则递归地在左子树中删除它
    else if(n > root->data)
        root->rchild = bstRemove(root->rchild, data);

    // 若data恰好就是根节点,则分如下几种情况:  
    else
    {
        // a. 根节点若有左子树,则用左子树中最大的节点max替换根节点
        //    并在左子树中递归删除max  
        if(root->lchild != NULL)
        {
            node *max;
            for(max=root->lchild; max->rchild!=NULL;
                max=max->rchild);

            root->data = max->data;
            root->lchild = bstRemove(root->lchild, max->data);
        }

        // b. 否则,若有右子树,则用右子树中最小的节点min替换根节点
        //    并在右子树中递归删除min  
        else if(root->rchild != NULL)
        {
            for(tmp=root->rchild; tmp->lchild!=NULL;
                tmp=tmp->lchild);

            root->data = tmp->data;
            root->rchild = bst_remove(root->rchild, tmp->data);
        }

        // c. 否则,直接删除根节点
        else
        {
            free(root);
            return NULL;
        }
    }

    return root;
}

遍历

// 前序遍历
void preOrder(node *root)
{
    if(root == NULL)
        return;

    // 先访问根节点
    printf("%d", root->data);

    // 再依次使用前序算法,遍历其左、右子树
    preOrder(root->lchild);
    preOrder(root->rchild);
}

// 中序遍历
void inOrder(node *root)
{
    if(root == NULL)
        return;

    // 先访问左子树
    inOrder(root->lchild);

    // 再访问根节点
    printf("%d", root->data);

    // 再访问右子树
    inOrder(root->rchild);
}

// 后序遍历
void postOrder(node *root)
{
    if(root == NULL)
        return;

    // 先依次使用后序算法,遍历其左、右子树
    postOrder(root->lchild);
    postOrder(root->rchild);

    // 再访问根节点
    printf("%d", root->data);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值