递归删除树的节点

// 左孩子< 父节点 < 右孩子,不是二叉平衡树

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

// 管理节点
typedef struct BstNode
{
    int data;
    struct BstNode *lchild;
    struct BstNode *rchild;
} BstNode;

#define NODE BstNode
#include "drawtree.h"

// 初始化节点
BstNode *init_node(int data)
{
    BstNode *p = malloc(sizeof(BstNode));
    if (p == NULL)
    {
        return NULL;
    }
    p->data = data;
    p->lchild = NULL;
    p->rchild = NULL;
    return p;
}

// 插入节点
BstNode *insert_node(BstNode *root, int data)
{
    BstNode *pnew = init_node(data); // 为新节点初始化
    if (pnew == NULL)
    {
        return NULL;
    }

    // 寻找在哪里插入新节点
    BstNode *p = root;
    if (root == NULL) // 如果根节点为空,插入根节点
    {
        root = pnew;
    }
    else
    {
        while (1) // 循环查找叶子节点,然后插入
        {
            if (data > p->data)
            {
                if (p->rchild == NULL)
                {
                    p->rchild = pnew;
                    break;
                }
                else
                {
                    p = p->rchild;
                }
            }
            else if (data < p->data)
            {
                if (p->lchild == NULL)
                {
                    p->lchild = pnew;
                    break;
                }
                else
                {
                    p = p->lchild;
                }
            }
            else
            {
                printf("该数已经插入树中,无法重复插入\n");
            }
        }
    }

    return root;
}

// 创建一个树
BstNode *create_BstTree()
{
    BstNode *root = NULL; // 刚开始根节点为空,这时还没有为root开辟空间
    int data;             // 插入节点的值,等会自己赋值

    // 开始循环赋值,输入非数字的会结束建树
    while (1)
    {
        if (0 == scanf("%d", &data)) // 判断结束条件
        {
            while (getchar() != '\n') // 取走缓冲区的字符
                ;
            break;
        }
        root = insert_node(root, data); // 插入节点后需要跟新,所以用root接受
    }
    return root;
}

// 前序
void pre_order(BstNode *root)
{
    if (root == NULL)
    {
        return;
    }
    // 跟左右
    printf("%d\t", root->data);
    pre_order(root->lchild);
    pre_order(root->rchild);
}

// 中序
void mid_order(BstNode *root)
{
    if (root == NULL)
    {
        return;
    }
    // 左根右
    mid_order(root->lchild);
    printf("%d\t", root->data);
    mid_order(root->rchild);
}

// 后序
void post_order(BstNode *root)
{
    if (root == NULL)
    {
        return;
    }
    // 左右根
    post_order(root->lchild);
    post_order(root->rchild);
    printf("%d\t", root->data);
}

// 递归删除节点
BstNode *remove_node(BstNode *root, int data)
{
    if (root == NULL)
    {
        return NULL;
    }

    if (root->data > data) // 如果小于要删除的数,进入该节点的左孩子,继续调用remove()函数
    {
        root->lchild = remove_node(root->lchild, data);
    }

    else if (root->data < data) // 大于......
    {
        root->rchild = remove_node(root->rchild, data);
    }

    else // 找到要删除的节点
    {

        if (root->lchild != NULL) // 只有左
        {
            BstNode *p = NULL;
            for (p = root->lchild; p->rchild != NULL; p = p->rchild) // 找左子树的最大值
                ;
            root->data = p->data;
            root->lchild = remove_node(root->lchild, p->data);
        }

        else if (root->rchild != NULL) // 只有右
        {
            BstNode *p = NULL;
            for (p = root->rchild; p->lchild != NULL; p = p->lchild) // 找右子树的最小值
                ;
            root->data = p->data;
            root->rchild = remove_node(root->rchild, p->data);
        }

        else // 叶子节点
        {
            free(root);
            return NULL;
        }
    }

    return root;
}

int main(int argc, char const *argv[])
{
    BstNode *root = create_BstTree();
    if (root == NULL)
    {
        printf("建树失败\n");
        return -1;
    }

    // 前,中,后序遍历
    pre_order(root);
    // mid_order(root);
    // post_order(root);
    printf("\n");

    // 递归删除节点
    root = remove_node(root, 10);
    draw(root); // 画图用的,可以删掉,不能直接用,没有头文件用不了
    pre_order(root);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值