二叉排序树详解及其C语言简单实现

定义

  二叉排序树(Binary Sort Tree)又称二叉查找树(Binary Search Tree),也称为二叉搜索树。二叉排序树或者是一棵空树,或者是具有下列特点的二叉树:

1. 若左子树不空,其左子树上所有结点的值均小于它的根结点的值;
2. 若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
3. 结点的左、右子树也分别是一个二叉排序树.

如下为一个典型的二叉搜索树:
在这里插入图片描述

二叉排序树的基本操作

1 二叉树的构建

  目前含有如下元素 23, 19, 29, 16, 21, 32, 20,其构建流程为:

1  首先插入元素23;
2  元素19小于元素23,根据规则将19插入23的左子树中;
3  元素29大于元素23,根据规则将29插入23的右子树中;
4  元素16小于元素19,根据规则将16插入19的左子树中;
5  元素21大于元素19小于元素23,根据规则将21插入19的右子树中;
6  元素32大于元素29,根据规则将32插入29的右子树中;
7  元素20大于元素19小于元素21,根据规则将20插入21的左子树中;

在这里插入图片描述

2 二叉搜索树的查找操作

例:从上述二叉搜索树查找元素 21,流程如下:23 --> 19 --> 21

1  首先与根节点进行比较,21 小于 23,可知应在其左子树中进行查找;
2  元素19小于元素21,根据规则应在元素19的右子树中进行查找;
3  元素21大于元素21,成功查找到,结束。

在这里插入图片描述

3 二叉搜索树的插入操作

向上述二叉搜索树中插入元素 22,流程如下【首先找到插入位点,插入位点为叶子结点的指针域中,后修改父节点的指针域】:

1  根据查找规则找到插入位点,即插入位点为元素 21的右子树中;
2  将元素21 的右指针域指向元素 22。
在这里插入图片描述

4 二叉搜索树的删除操作
4.1 删除元素为叶子结点,无左右子树(看图更明了)

在这里插入图片描述

4.2 删除元素非叶子结点,但含有子左右子树中的一个(看图更明了)

在这里插入图片描述

4.3 删除元素为非叶子结点,同时含有左右子树,该情况稍复杂

1  根据查找规则找到删除元素;
2  确定右子树,找到右子树中的最小值元素 xmin。
3  将待删除元素与xmin互换位置,更新对应的指针域信息
在这里插入图片描述

源代码实现

binary_sort_tree.h

#ifndef BINARY_SORT_TREE_H
#define BINARY_SORT_TREE_H

typedef int Elemtype;

typedef enum
{
    TRUE,
    FALSE,
    NON_ALLOCATED
} Status;

typedef struct BSNode{
    Elemtype item;
    struct BSNode *lchild;
    struct BSNode *rchild;
} BSNode;

typedef struct BStree{
    BSNode *root;
    int size;
} BSTree;


void InitBSTree(BSTree *ptree);
Status BSTreeIsFull(const BSTree *ptree);
Status BSTreeIsEmpty(const BSTree *ptree);
Status BSTreeSearch(const BSTree *ptree, Elemtype key);
Status BSTreeInsert(BSTree *ptree, Elemtype key);
Status BSTreeDelete(BSTree *ptree, Elemtype key);
int BSTreeDepth(const BSTree *ptree);
void InorderShowBSTree(const BSTree *ptree);
void PostShowBSTree(const BSTree *ptree);
void DeleteAll(BSTree *ptree);

#endif //BINARY_SORT_TREE_H
#include <stdio.h>
#include <stdlib.h>
typedef struct pair
{
    BSNode *parent;
    BSNode *child;
} pair;

static BSNode *MakeNode(const Elemtype key);
static void AddNode(BSNode *newnode, BSNode *root);
static void DeleteNode(BSNode **delnode);
static pair Seek(const BSTree *ptree, Elemtype key);
static void traverse(BSNode *root);
static void DeleteAllNode(BSNode *root);

void InitBSTree(BSTree *ptree)
{

    ptree->root = NULL;
    ptree->size = 0;
}

Status BSTreeIsFull(const BSTree *ptree)
{
    BSNode *tmp = (BSNode *)malloc(sizeof(BSNode));
    if (tmp == NULL)
        return TRUE;

    else
        return FALSE;
}

Status BSTreeIsEmpty(const BSTree *ptree)
{
    if (ptree->size == 0)
        return TRUE;
    else
        return FALSE;
}

Status BSTreeSearch(const BSTree *ptree, Elemtype key)
{
    return (Seek(ptree, key).child == NULL ? FALSE : TRUE);
}

Status BSTreeInsert(BSTree *ptree, Elemtype key)
{
    BSNode *newnode;

    if (Seek(ptree, key).child != NULL)
    {
        printf("erroe, do not insert same elemnt of BSTree\n");
        return FALSE;
    }

    newnode = MakeNode(key);
    if (newnode == NULL)
    {
        printf("error, can not create a BSNode since out of memory!\n");
        return FALSE;
    }

    if(ptree->root == NULL)
        ptree->root = newnode;
    
    else
        AddNode(newnode, ptree->root);

    ptree->size++;

    return TRUE;
}

Status BSTreeDelete(BSTree *ptree, Elemtype key)
{
    pair look;
    if (!BSTreeIsEmpty(ptree))
    {
        printf("BSTree is empty!!!\n");
        return FALSE;
    }

    look = Seek(ptree, key);

    if (look.child == NULL)
    {
        printf("delete element is not exist!\n");
        return FALSE;
    }

    else if (look.parent == NULL)
    {
        DeleteNode(&look.parent);
    }

    else if (look.parent->lchild == look.child)
        DeleteNode(&look.parent->lchild);

    else if (look.parent->rchild == look.child)
        DeleteNode(&look.parent->rchild);

    ptree->size--;

    return TRUE;
}

void InorderShowBSTree(const BSTree *ptree)
{
    if (ptree != NULL)
        traverse(ptree->root);
    printf("\n");
}

static BSNode *MakeNode(const Elemtype key)
{
    BSNode *new_node = (BSNode *)malloc(sizeof(BSNode));

    if (new_node != NULL)
    {
        new_node->item = key;
        new_node->lchild = NULL;
        new_node->rchild = NULL;
    }
    return new_node;
}

static void traverse(BSNode *root)
{
    if (root == NULL)
        return;

    traverse(root->lchild);
    printf("%d\t", root->item);
    traverse(root->rchild);
}

void FreeBSTree(BSTree *ptree)
{
    if (ptree != NULL)
        DeleteAllNode(ptree->root);

    ptree->size = 0;
    ptree->root = NULL;
}

static pair Seek(const BSTree *ptree, Elemtype key)
{
    pair look;
    look.parent = NULL;
    look.child = ptree->root;

    if (look.child == NULL)
        return look;

    while (look.child != NULL)
    {
        if (key < look.child->item)
        {
            look.parent = look.child;
            look.child = look.child->lchild;
        }

        else if (key > look.child->item)
        {
            look.parent = look.child;
            look.child = look.child->rchild;
        }
        else
        {
            break;
        }
    }
    return look;
}

static void AddNode(BSNode *newnode, BSNode *root)
{
    if (root->item > newnode->item)
    {
        if (root->lchild == NULL)
            root->lchild = newnode;
        else
        {
            AddNode(newnode, root->lchild);
        }
    }

    else if (root->item < newnode->item)
    {
        if (root->rchild == NULL)
            root->rchild = newnode;
        else
            AddNode(newnode, root->rchild);
    }

    else
    {
        printf("location error !!!\n");
        exit(1);
    }
}


int Max_Depth(BSNode *root)
{
    if(root == NULL)
        return 0;

    int leftdepth = Max_Depth(root->lchild);
    int rightdepth = Max_Depth(root->rchild);

    return (leftdepth > rightdepth) ? leftdepth + 1 : rightdepth + 1;
}

int BSTreeDepth(const BSTree *ptree)
{
    if(ptree != NULL)
    {
        return  Max_Depth(ptree->root);
    }
}

static void DeleteNode(BSNode **delnode)
{
    BSNode *temp;

    if ((*delnode)->lchild == NULL)
    {
        temp = *delnode;
        (*delnode) = (*delnode)->rchild;
        free(temp);
    }

    else if ((*delnode)->rchild == NULL)
    {
        temp = *delnode;
        (*delnode) = (*delnode)->lchild;
        free(temp);
    }

    else
    {
        for (temp = (*delnode)->lchild; temp->rchild; temp = temp->rchild)
            break;

        temp->rchild = (*delnode)->rchild;
        temp = *delnode;
        (*delnode) = (*delnode)->lchild;
        free(temp);
    }
}

static void DeleteAllNode(BSNode *root)
{
    if (root == NULL)
        return;

    BSNode *pright;
    {
        pright = root->rchild;    // 指向右子树
        DeleteAllNode(root->lchild); // 递归删除最左子树节点
        free(root);               // 删除中节点
        DeleteAllNode(pright);       // 删除右节点
    }
}

void DeleteAll(BSTree *ptree)
{
    if(ptree != NULL)
        DeleteAllNode(ptree->root);
    ptree->root = NULL;
    ptree->size = 0;
}

int main()
{
    BSTree root;
    InitBSTree(&root);
    BSTreeInsert(&root, 23);
    BSTreeInsert(&root, 34);
    BSTreeInsert(&root, 13);
    InorderShowBSTree(&root);

    printf("The max_depth is %d\n", BSTreeDepth(&root));

    BSTreeDelete(&root, 34);

    Status result = BSTreeSearch(&root, 43);
   
    if (result == TRUE)
    {
        printf("Found it\n");
    }   

    else
        printf("Not Found\n");

    InorderShowBSTree(&root);

    DeleteAll(&root);
    return 0;
}

测试结果如下所示:
在这里插入图片描述

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值