C语言二叉搜索树

学着写了一个二叉搜索数,大部分是按照书本上的思路写的,有抄袭嫌疑,不过所有代码都是我手打的,且在写的过程中是不看书的,调试过程中对照了一下书。这个树只能存储不同的元素值,即元素的值不能相同,由于树的自相似性,在写的过程中用到了大量的递归,一直觉得递归很难理解,能写递归的都是大神,今天在资料的帮助下也写了一点递归,感觉对递归的理解上升了一点,还是那句话,书读百页不如手打一行。

BinarySearchTree.h

/************************************
*二叉查找树
*作者:JK
*日期:2014-08-11
*************************************/

#ifndef _BINARY_SEARCH_TREE_HEADER_H_
#define _BINARY_SEARCH_TREE_HEADER_H_


struct TreeNode;
typedef struct TreeNode* Position;
typedef struct TreeNode* SearchTree;
typedef int ElemType;

struct TreeNode
{
    ElemType elem;    // 元素
    SearchTree left;  // 左子树
    SearchTree right; // 右子树
};

SearchTree InitTree(SearchTree T);
SearchTree MakeEmpty(SearchTree T);
Position Find(ElemType E, SearchTree T);
Position FindMin(SearchTree T);
Position FindMax(SearchTree T);
SearchTree Insert(ElemType E, SearchTree T);
SearchTree Delete(ElemType E, SearchTree T);
ElemType Retrieve(Position P);

#endif
BinarySearchTree.c

#include <assert.h>
#include <stddef.h>
#include "BinarySearchTree.h"

/***************************************
*功能:初始化,将指向根的指针设置位NULL
*参数:T:待初始化的树
*返回值:初始后后的树
****************************************/
SearchTree InitTree(SearchTree T)
{
    T = NULL;
    return T;
}

/********************************
*功能:采用递归方法清空一个二叉查找树
*参数:T:待清空的树
*返回值:返回NULL
*********************************/
SearchTree MakeEmpty(SearchTree T)
{
    if (T != NULL)
    {
        MakeEmpty(T->left);
        MakeEmpty(T->right);
        free(T);
    }

    return NULL;
}

/********************************
*功能:在树中查找元素大小与E相等的元素位置
*参数:E:待查参数,T:待查的树
*返回值:成功返回位置,失败返回NULL
*********************************/
Position Find(ElemType E, SearchTree T)
{
    if (T == NULL)
    {
        return NULL;
    }

    if (E < T->elem)
    {
        return Find(E, T->left);
    }
    else if (E > T->elem)
    {
        return Find(E, T->right);
    }

    return T;
}

/********************************
*功能:查找树中的最大值
*参数:T:待查的树
*返回值:成功返回位置,失败返回NULL
*********************************/
Position FindMax(SearchTree T)
{
    if (T != NULL)
    {
        while (T->right != NULL)
        {
            T = T->right;
        }
        return T;
    }
    return NULL;
}

/********************************
*功能:查找树中的最大值(递归实现)
*参数:T:待查的树
*返回值:成功返回位置,失败返回NULL
*********************************/
/*
Position FindMax(SearchTree T)
{
    if (T == NULL)
    {
        return NULL;
    }
    else if (T->right == NULL)
    {
        return T;
    }
    else
    {
        return FindMax(T->right);
    }
}
*/

/********************************
*功能:查找树中的最小值
*参数:T:待查的树
*返回值:成功返回位置,失败返回NULL
*********************************/
Position FindMin(SearchTree T)
{
    if (T != NULL)
    {
        while(T->left != NULL)
        {
            T = T->left;
        }
        return T;
    }
    return NULL;
}

/********************************
*功能:查找树中的最小值(递归实现)
*参数:T:待查的树
*返回值:成功返回位置,失败返回NULL
*********************************/
/*
Position FindMin(SearchTree T)
{
    if (T == NULL)
    {
        return NULL;
    }
    else if (T->left == NULL);
    {
        return T;
    }
    else
    {
        return FindMin(T->left);
    }
}
*/


/********************************
*功能:插入元素(递归实现),元素都插在了叶上
*参数:E:待插入的元素值;T:待插入的树
*返回值:返回该树
*********************************/
SearchTree Insert(ElemType E, SearchTree T)
{
    if (T == NULL)
    {
        T = malloc(sizeof(struct TreeNode));
        assert(T != NULL);
        T->elem = E;
        T->right = NULL;
        T->left = NULL;
    }
    else if (E < T->elem)
    {
        T->left = Insert(E, T->left);
    }
    else if (E > T->elem)
    {
        T->right = Insert(E, T->right);
    }

    return T;
}

/********************************
*功能:删除元素(递归实现)
*参数:E:待删除的元素值;T:待删除值的树
*返回值:返回该树
*********************************/
SearchTree Delete(ElemType E, SearchTree T)
{
    Position tmpPos;
    if (T == NULL)
    {
        printf("element not found\n");
    }
    else if (E < T->elem)
    {
        T->left = Delete(E, T->left);// 到左边删
    }
    else if (E > T->elem)
    {
        T->right = Delete(E, T->right);// 到右边删
    }
    else if (T->left && T->right)// 找到该元素且有两个儿子
    {
        tmpPos = FindMin(T->right);// 找到该元素右子树的最小值
        T->elem = tmpPos->elem;// 将需要删除的值替换位右子树中的最小值
        T->right = Delete(T->elem, T->right);// 删除右子树中的最小值
    }
    else// 找到该元素且只有一个或没有儿子
    {
        tmpPos = T;
        if (T->left == NULL)
        {
            T = T->right;
        }
        else if (T->right == NULL)
        {
            T = T->right;
        }
        free(tmpPos);

    }
    return T;
}

/***********************************************
*功能:获取节点上的元素值
*参数:P:指向节点的指针
*返回值:元素值,为了防止警告,P是NULL时返回零
***********************************************/
ElemType Retrieve(Position P)
{
    if (P != NULL)
    {
        return P->elem;
    }
    printf("retrieve failed, NULL pointer\n");
    return 0;
}

测试主函数main.c

#include <stdio.h>
#include <stdlib.h>
#include "BinaryTree.h"

int main()
{
    printf("Hello world JK!\n");
    SearchTree myTree = InitTree(myTree);

    myTree = Insert(50, myTree);// 根

    // 随机插入50个0~99之间元素
    int i = 0;
    for (i = 0; i < 50;  ++i)
    {
        myTree = Insert(rand()%100, myTree);
    }

    // 插入40
    myTree = Insert(40, myTree);

    // 查找40
    Position p = Find(40, myTree);
    int elemValue = Retrieve(p);
    printf("find 40:%d\n", elemValue);

    // 寻找最大值
    p = FindMax(myTree);
    elemValue = Retrieve(p);
    printf("Max element:%d\n", elemValue);

    // 寻找最小值
    p = FindMin(myTree);
    elemValue = Retrieve(p);
    printf("Min element:%d\n", elemValue);

    // 删除元素
    myTree = Delete(30, myTree);

    // 清空
    myTree = MakeEmpty(myTree);


    return 0;
}

测试结果:


<think>嗯,用户让我详细介绍一下C语言中的二叉搜索树。首先,我得确认用户的基础知识水平。可能他们已经学过数据结构的基础,比如链表或者二叉树,但也许对二叉搜索树的具体实现不太清楚。需要从基本概念讲起,再逐步深入到操作和代码实现。 二叉搜索树的定义是关键,必须明确每个节点的左子树都小于节点,右子树都大于节点。这个特性决定了它的高效查找、插入和删除操作。接下来需要介绍结构体的定义,比如节点包含的数据和左右指针。 然后,操作部分要分点讲解。查找操作相对简单,递归和迭代两种方法都可以。插入操作需要考虑树为空的情况,以及如何递归地找到正确的位置。删除操作比较复杂,需要分三种情况处理:无子节点、有一个子节点、有两个子节点。特别是第三种情况,需要找到前驱或后继节点来替换,这部分容易出错,得详细说明。 代码示例是必要的,用户可能需要实际的例子来理解理论。每个函数的实现,比如search、insert、delete_node,都要解释清楚。特别是删除函数中的三种情况处理,要用代码展示如何操作指针,避免内存泄漏。 最后,应用场景和优缺点能帮助用户理解二叉搜索树的实际用途,比如数据库索引或文件系统。同时,要提到平衡二叉树的重要性,因为不平衡会导致性能下降,这样用户知道后续学习的方向。 检查一下是否有遗漏的部分,比如遍历方式或者常见错误。可能用户还想知道如何测试这些函数,或者如何处理重复的值,但问题中没有提到,是否需要补充?不过据问题描述,用户可能只需要基础详解,所以保持核心内容即可。确保解释清晰,代码正确,逻辑连贯。</think>### 二叉搜索树Binary Search Tree, BST)详解 #### 一、基本概念 **二叉搜索树**是一种特殊的二叉树数据结构,满足以下性质: 1. **左子树**所有节点的值 < 节点的值 2. **右子树**所有节点的值 > 节点的值 3. 左右子树也必须是二叉搜索树 这一特性使得BST在查找、插入和删除操作时具有高效性,平均时间复杂度为 **O(log n)**(平衡状态下)。 --- #### 二、C语言实现基础 **1. 节点结构定义** ```c typedef struct TreeNode { int data; struct TreeNode* left; struct TreeNode* right; } TreeNode; ``` **2. 核心操作** - **查找节点** ```c TreeNode* search(TreeNode* root, int key) { if (root == NULL || root->data == key) return root; return (key < root->data) ? search(root->left, key) : search(root->right, key); } ``` - **插入节点** ```c TreeNode* insert(TreeNode* root, int val) { if (root == NULL) { TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode)); newNode->data = val; newNode->left = newNode->right = NULL; return newNode; } if (val < root->data) root->left = insert(root->left, val); else if (val > root->data) root->right = insert(root->right, val); return root; // 忽略重复值 } ``` - **删除节点**(最复杂操作) ```c TreeNode* deleteNode(TreeNode* root, int key) { if (!root) return NULL; if (key < root->data) { root->left = deleteNode(root->left, key); } else if (key > root->data) { root->right = deleteNode(root->right, key); } else { // Case 1/2: 0-1个子节点 if (!root->left) { TreeNode* temp = root->right; free(root); return temp; } else if (!root->right) { TreeNode* temp = root->left; free(root); return temp; } // Case 3: 两个子节点,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值