一波C语言二元查找树算法题目解答实例汇总

一波C语言二元查找树算法题目解答实例汇总

什么是二元查找树?

二元查找树,又称为二叉搜索树,是一种非常常见的数据结构,它的主要特点是左子树所有节点的值小于其根节点的值,右子树所有节点的值大于其根节点的值。该策略保证整个树的左子树所有节点小于根节点,右子树所有节点大于根节点。

二元查找树可以用来做很多问题,例如查找、插入、删除等。

二元查找树算法题目解答实例汇总

下面我们将对几个常见的二元查找树算法题目进行讲解。

题目一: 向二元查找树中插入节点

实现一个函数,将一个整数插入到二元查找树中。

struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
};

struct TreeNode* insertIntoBST(struct TreeNode* root, int val){
    if (root == NULL) {
        root = malloc(sizeof(struct TreeNode));
        root->val = val;
        root->left = NULL;
        root->right = NULL;
    } else {
        if (root->val < val) {
            root->right = insertIntoBST(root->right, val);
        } else if (root->val > val) {
            root->left = insertIntoBST(root->left, val);
        } else {
            // do nothing
        }
    }
    return root;
}

以上代码通过递归将值插入二元查找树中。如果根节点为空,则新建一个根节点并返回;如果插入的值小于根节点,则继续递归左子树;如果插入的值大于根节点,则递归右子树。如果插入的值已经存在,则不进行任何操作。

题目二: 在二元查找树中删除节点

实现一个函数,将一个给定的值从二元查找树中删除。如果树中节点数小于等于1,则删除整个树。

struct TreeNode* deleteNode(struct TreeNode* root, int key) {
    if (root == NULL) {
        return NULL;
    }

    if (root->val == key) {
        // 如果是叶子节点,则直接删除
        if (root->left == NULL && root->right == NULL) {
            free(root);
            root = NULL;
        } else if (root->left == NULL) {
            // 如果只有右孩子,则将右孩子上升为新的根节点
            struct TreeNode *tmp = root;
            root = root->right;
            free(tmp);
        } else if (root->right == NULL) {
            // 如果只有左孩子,则将左孩子上升为新的根节点
            struct TreeNode *tmp = root;
            root = root->left;
            free(tmp);
        } else {
            // 如果有两个孩子,则将右子树的最小值作为新的根节点
            struct TreeNode *tmp = root->right;
            while (tmp->left != NULL) {
                tmp = tmp->left;
            }
            root->val = tmp->val;
            root->right = deleteNode(root->right, tmp->val);
        }
    } else if (root->val < key) {
        root->right = deleteNode(root->right, key);
    } else {
        root->left = deleteNode(root->left, key);
    }

    return root;
}

以上代码通过递归将给定值从二元查找树中删除。如果根节点为空,则返回 NULL;如果要删除的值小于根节点,则继续递归左子树;如果要删除的值大于根节点,则递归右子树。如果要删除的值等于根节点,需要考虑以下三种情况:

  • 如果要删除的节点是叶子节点,则直接删除。
  • 如果要删除的节点只有一个孩子,则将该孩子上升为新的根节点。
  • 如果要删除的节点有两个孩子,则将右子树的最小值作为新的根节点。

示例一:向二元查找树中插入节点

例如,将数组 [4,2,7,1,3] 转换成二元查找树,代码如下:

struct TreeNode* root = NULL;
for (int i = 0; i < 5; i++) {
    root = insertIntoBST(root, nums[i]);
}

其中 nums 数组为 [4,2,7,1,3],表示要插入的数。插入后的二元查找树如下所示:

      4
     / \
    2   7
   / \
  1   3

示例二:在二元查找树中删除节点

例如,删除数值为 2 的节点进行重建,代码如下:

root = deleteNode(root, 2);

重建后的二元查找树如下所示:

      4
     / \
    3   7
   /
  1

总结

二元查找树是一种非常有用的数据结构,可以用来解决很多问题。通过上述两个题目的讲解,希望大家能够更加深入的了解二元查找树的相关知识。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:一波C语言二元查找树算法题目解答实例汇总 - Python技术站

(0)
上一篇 2023年5月22日
下一篇 2023年5月22日

相关文章

  • C++中对象的赋值与复制操作详细解析

    C++中对象的赋值与复制操作详细解析 对于C++开发者来说,对象的赋值和复制操作是非常常见的操作,然而,它们并不总是像我们想象中的那样简单,不合理的复制操作甚至会导致程序崩溃。本文将详细讲解C++中对象的赋值和复制操作。 赋值操作符 当我们创建一个对象并赋值给另一个对象时,我们需要使用赋值操作符(=)。如下所示: MyClass obj1; MyClass …

    C 2023年5月22日
    00
  • 算法详解之分支限界法的具体实现

    算法详解之分支限界法的具体实现 什么是分支限界法? 分支限界法是一种用于解决优化问题的算法。它通过分解问题成许多子问题,并考虑每个子问题的潜在解决方案,逐步推进过程,直到找到最优解。分支限界法首先生成初始解,并对所有可能的解进行评估,从中选择最优解来进行下一步的搜索。 具体实现 分支限界法的具体实现可以分为以下步骤: 生成初始解: 对于给定的问题,通过一定的…

    C 2023年5月22日
    00
  • C++如何切割String对象的方法

    C++有多种方法可以切割String对象,下面介绍其中两种。 方法一:使用stringstream stringstream是一个可用于输入和输出的字符串流类。可以通过向其写入字符串,再从中读取字符串,实现将字符串按照指定分隔符进行切割的功能。 示例代码如下: #include <iostream> #include <string>…

    C 2023年5月22日
    00
  • 用实际代码演示Ruby的容易被误解的6个特性

    下面是用实际代码演示Ruby的容易被误解的6个特性的完整攻略。 1. 变量作用域 Ruby 中的变量作用域可能会让人感到有些混乱。首先,Ruby 有全局变量、实例变量、类变量和局部变量四种。而且,Ruby 采用的是静态作用域,也就是说,变量的作用域是在写代码时决定的,而非在运行时决定的。 $a = 10 def test puts $a end test #…

    C 2023年5月23日
    00
  • 关于JSON与JSONP简单总结

    关于JSON与JSONP简单总结 什么是JSON? JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。 JSON格式如下: { "name": "John", "age": 30, "country&qu…

    C 2023年5月23日
    00
  • 解决@Transactional注解事务不回滚不起作用的问题

    解决@Transactional注解事务不回滚不起作用的问题的详细攻略如下: 问题描述 在进行数据库操作时,我们通常会使用@Transactional注解来保证事务的原子性,但在使用过程中可能会出现事务不回滚不起作用的问题,导致数据一旦出现异常就无法恢复。这种情况通常是因为注解失效或者配置不正确导致的。 解决方案 1. 配置文件中开启事务管理器 我们可以在配…

    C 2023年5月23日
    00
  • C++使用CriticalSection实现线程同步实例

    下面我将为您介绍在 C++ 中使用 CriticalSection 实现线程同步的攻略。 什么是 CriticalSection CriticalSection 是一种线程同步机制,它的目的是为了保证多线程环境下对共享变量的读写操作的正确性,防止出现竞争条件导致的数据错误。 在 C++ 中,CriticalSection 是由 Windows API 提供的…

    C 2023年5月22日
    00
  • 详解如何在Go语言中调用C源代码

    下面我将为你详细讲解如何在Go语言中调用C源代码。 调用C源代码的前置条件 在开始调用C源代码之前,你需要确保你的计算机已经安装了C编译器,并且你需要掌握一些C语言的基础知识。 在Go语言中调用C源代码的步骤 在Go语言中调用C源代码的步骤如下: 1.定义C函数的原型首先,你需要使用Go语言的Cgo工具来定义C函数的原型。这可以通过在Go语言中使用C语言风格…

    C 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部