用 C 语言实现二叉查找树(BST):插入与遍历

二叉查找树(Binary Search Tree, BST)是一种在查找、插入、删除操作方面效率较高的基础数据结构。它广泛应用于各种算法与系统中,如数据库索引、集合容器等。

本文将使用 C 语言实现一个完整的 BST,并支持以下功能:

  • 创建树
  • 插入节点
  • 前序 / 中序 / 后序遍历

项目说明与设计目标

/**
 * @file name : BST.c
 * @brief     : 设计一个BST二叉查找树,为了方便对二叉树进行增删,所以采用双向不循环链表,
 *              每个节点的内部都需要有两个指针,分别指向该节点的左子树(lchild)和右子树(rchild)
 * @author    : qrshxc@163.com
 * @date      : 2025/05/08
 * @version   : 1.0
 * @note      : 
 * CopyRight (c)  2025-2026   qrshxc@163.com   All Right Reseverd
 */

说明
该程序实现了 BST 的基本结构与插入功能,数据结构设计为每个节点包含一个整型键值,以及两个指向左右子树的指针,便于实现递归插入与遍历操作。

数据结构定义

// BST树中结点有效键值的数据类型
typedef int DataType_t;

// 构造BST树中的结点
typedef struct BSTreeNode
{
    DataType_t   data;         // 结点的键值
    struct BSTreeNode *lchild; // 左子树的指针域
    struct BSTreeNode *rchild; // 右子树的指针域
} BSTree_t;

说明

  • data:当前节点的键值(本例为整型)
  • lchild:指向左子树的指针
  • rchild:指向右子树的指针

创建节点函数

创建根节点

/**
 * @name       BSTree_Create
 * @brief      创建一个带键值的根结点,并进行初始化
 * @param      data 节点的键值
 * @return
 *     @retval root 根节点   
 * @date       2025/05/08
 * @version    1.0
 * @note       
 */
BSTree_t * BSTree_Create(DataType_t data)
{
    // 给根结点申请一片内存
    BSTree_t *root = (BSTree_t *)calloc(1, sizeof(BSTree_t));
    
    // 错误处理
    if (root == NULL)
    {
        perror("calloc memory for root failed!");
        exit(-1);
    }
    
    // 对根结点进行初始化
    root->data   = data;
    root->lchild = NULL;
    root->rchild = NULL;
    
    // 返回头结点地址
    return root;
}

创建普通新节点

/**
 * @name       BSTree_NewNode
 * @brief      创建新结点,并进行初始化
 * @param      data 结点的键值
 * @return
 *     @retval NewNode 新结点     
 * @date       2025/05/08
 * @version    1.0
 * @note       
 */
BSTree_t *BSTree_NewNode(DataType_t data)
{
    // 给新结点申请一片内存
    BSTree_t *NewNode = (BSTree_t *)calloc(1, sizeof(BSTree_t));
    
    // 错误处理
    if (NewNode == NULL)
    {
        perror("calloc memory for NewNode failed!");
        return NULL;
    }
    
    // 对新结点进行初始化
    NewNode->data = data;
    NewNode->lchild = NULL;
    NewNode->rchild = NULL;
    
    // 返回新结点地址
    return NewNode;
}

插入节点函数

/**
 * @name       BSTree_InsertNode
 * @brief      向BST树中加入结点 
 * @param      root  树的根节点指针的指针
 * @param      data  要插入的键值
 * @return
 *     @retval true  插入成功    
 *     @retval false 插入失败   
 * @version    1.0
 * @note       规则:左子树的键值 < 根节点键值 < 右子树的键值
 */
bool BSTree_InsertNode(BSTree_t *root,DataType_t data)
{
    // 备份根节点
    BSTree_t *proot = root;
    // 创建新节点
    BSTree_t *NewNode = BSTree_NewNode(data);

    if (NewNode == NULL)
    {
        printf("Can not insert new node\n");
        return false;
    }

    // 判断BST树是否为空树,此时为两种情况(空 or 不空)
    if (root == NULL)
    {
        // 1.空树
        root = NewNode; // 新结点作为根结点
        return true;
    }else
    {
        // 2.非空树,此时分三种情况(1.新结点键值比等于根结点键值 2.新结点键值小于根结点键值 3.新结点键值大于根结点键值)
        while(proot)
        {
            // 1.新结点键值比等于根结点键值
            if (NewNode->data == proot->data)
            {
                printf("Can not insert new node,they are equal!");
                return false;
            }
            // 2.新结点键值小于根结点键值
            else if (NewNode->data < proot->data)
            {
                if (proot->lchild == NULL)
                {
                     proot->lchild = NewNode; // 插入左子树
                     break;
                }
                proot = proot->lchild;
            }
            // 3.新结点键值大于根结点键值
            else
            {
                if (proot->rchild == NULL)
                {
                    proot->rchild = NewNode; // 插入右子树
                    break;
                }
                proot = proot->rchild;
            }
        }
    }

    return true;
}

测试及结果

int main()
{
    // 1. 创建一个带根节点的 BST 树
    BSTree_t *root = BSTree_Create(10);

    // 2. 向 BST 中插入若干新节点
    BSTree_InsertNode(root, 5);
    BSTree_InsertNode(root, 20);
    BSTree_InsertNode(root, 3);
    BSTree_InsertNode(root, 7);
    BSTree_InsertNode(root, 15);
    BSTree_InsertNode(root, 25);
    BSTree_InsertNode(root, 1);
    BSTree_InsertNode(root, 4);
    BSTree_InsertNode(root, 6);
    BSTree_InsertNode(root, 8);

    // 3. 前序遍历(根 → 左 → 右)
    printf("\n前序遍历(PreOrder)结果:\n");
    BSTree_PreOrder(root);

    // 4. 中序遍历(左 → 根 → 右)
    printf("\n中序遍历(InOrder)结果:\n");
    BSTree_InOrder(root);

    // 5. 后序遍历(左 → 右 → 根)
    printf("\n后序遍历(PostOrder)结果:\n");
    BSTree_PostOrder(root);
    
    return 0;
}

结果

前序遍历(PreOrder)结果:
keyval = 10
keyval = 5
keyval = 3
keyval = 1
keyval = 4
keyval = 7
keyval = 6
keyval = 8
keyval = 20
keyval = 15
keyval = 25

中序遍历(InOrder)结果:
keyval = 1
keyval = 3
keyval = 4
keyval = 5
keyval = 6
keyval = 7
keyval = 8
keyval = 10
keyval = 15
keyval = 20
keyval = 25

后序遍历(PostOrder)结果:
keyval = 1
keyval = 4
keyval = 3
keyval = 6
keyval = 8
keyval = 7
keyval = 5
keyval = 15
keyval = 25
keyval = 20
keyval = 10

在本篇博客中,我们从零开始,使用 C 语言手动实现了一个结构完整的 二叉查找树(BST),并详细解析了每个模块的实现逻辑。

这样不仅掌握了 C 语言中操作指针构建树结构的技巧,还深入理解了递归在二叉树结构中的重要地位。同时,本项目也为后续实现查找、删除、层序遍历、可视化等高级功能打下了坚实的基础。

posted @ 2025-05-12 20:55  九思0404  阅读(33)  评论(0)    收藏  举报