二叉搜索树

二叉搜索树是这样来的





节点是这样删的



//BST.h

#ifndef  _BST_H_
#define  _BST_H_
/*
 *在二叉排序树中,当根的左右子树存在时,其左子树上所有节点的值均小于根节点的值,右子树上所有节点的值均大于根节点的值
 */
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>

typedef int Elemenet;

typedef  struct _BST_Node
{
    Elemenet data;
    struct _BST_Node  *LChild;
    struct _BST_Node  *RChild;
}BST_Node;

typedef BST_Node *BST;

//初始化搜索树
void InitBST(BST *bst);

//插入
bool InsertBST(BST *bst, Elemenet v);

//最小节点值
Elemenet MinBST(const BST *bst);

//最大节点值
Elemenet MaxBST(const BST *bst);

//中序遍历(值由小到大)
void TraversalBST(const BST *bst);

//查找
BST_Node *SearchBST(const BST *bst, Elemenet key);

//删除
bool DeleteBST(BST *bst, Elemenet key);

//摧毁
void DestroyBST(BST *bst);

#endif //_BST_H_



//BST.c

#include "BST.h"

void InitBST(BST *bst)
{
    *bst = NULL;
}

//多个if( x ) return; return;的效率和if( x ){} else if( x )...else是一样的,判断次数一致,汇编代码也一样,貌似此处用后者逻辑更清楚些???
bool InsertBST(BST *bst, Elemenet v)
{
    if( NULL == *bst )
    {
        *bst = (BST_Node *)malloc(sizeof(BST_Node));
        if( NULL == *bst )
            return false;

        (*bst)->data = v;
        (*bst)->LChild = NULL;
        (*bst)->RChild = NULL;

        return true;
    }
    else if( v < (*bst)->data )
        return InsertBST(&(*bst)->LChild, v);
    else if( v > (*bst)->data )
        return  InsertBST(&(*bst)->RChild, v);
    else
        return false;                           //此种情况下,二叉搜索树中某个节点的值与待插值相等,为保证二叉树节点值的唯一性返回false
}

//如果左子树存在,那么最小节点应该在左子树上
Elemenet MinBST(const BST *bst)
{
    BST_Node *p = *bst;
    while (NULL != p->LChild)
        p = p->LChild;

    return p->data;
}

//如果右子树存在,最大节点应该在右子树上
Elemenet MaxBST(const BST *bst)
{
    BST_Node *p = *bst;
    while (NULL != p->RChild)
        p = p->RChild;

    return p->data;
}

//中序遍历(值由小到大)
void TraversalBST(const BST *bst)
{
    if( NULL == *bst )
        return ;

    TraversalBST(&(*bst)->LChild);
    printf("%d ", (*bst)->data);
    TraversalBST(&(*bst)->RChild);
}

BST_Node *SearchBST(const BST *bst, Elemenet key)
{
    if( NULL == *bst )
        return NULL;

    if( key < (*bst)->data )
        return SearchBST(&(*bst)->LChild, key);
    if( key > (*bst)->data )
        return SearchBST(&(*bst)->RChild, key);

    return *bst;
}

//多个if( x ) return; return;的效率和if( x ){} else if( x )...else是一样的,判断次数一致,汇编代码也一样
bool DeleteBST(BST *bst, Elemenet key)
{
    if( NULL == *bst )
        return false;

    if( key < (*bst)->data )
        return DeleteBST(&(*bst)->LChild, key);
    if( key > (*bst)->data )
        return DeleteBST(&(*bst)->RChild, key);

    //下面为找到目标删除节点的情况
    BST_Node *p = NULL;
    //目标删除节点的左右子树都存在(如节点59、32、68),可用左子树中的最大者或右子树中最小者的值替换目标删除节点,接着转化为删除左子树中的最大者或右子树中最小者
    if( NULL != (*bst)->LChild && NULL != (*bst)->RChild )
    {
        p = (*bst)->RChild;
        while (NULL != p->LChild)                           //寻找右子树中最小者
            p = p->LChild;

        (*bst)->data = p->data;                             //替换待目标删除节点
        return DeleteBST(&(*bst)->RChild, key);             //转化为删除右子树中最小者
    }
    else                                                    //目标删除节点最多只有一个子树(如2、52、60、69以及全部叶子节点)
    {
        p = *bst;
        if( NULL == (*bst)->LChild )                        //左子树为空(包含左子树为空,右子树不为空与左右子树均为空的情况)
        {
            *bst = (*bst)->RChild;                          //使指向目标删除节点的指针指向其可能存在的子树或空
        }
        else                                                //左子树不为空,右子树为空
        {
            *bst = (*bst)->LChild;                          //指向存在的右子树
        }
        free(p);

        return true;
    }
}

void DestroyBST(BST *bst)
{
    if( NULL == *bst )
        return;
    DestroyBST(&(*bst)->LChild);
    DestroyBST(&(*bst)->RChild);
    free(*bst);
    *bst = NULL;
}





//main.c

#include <stdio.h>
#include "BST.h"
#include <stdbool.h>

int main(int argc, char *argv[])
{
    BST bst;
    int array[10] = {59, 32, 68, 52, 60, 2, 69, 258, 17, 47};
    int i = 0;
    bool ret = true;

    InitBST(&bst);
    for(i = 0; i < 10 && ret; i++)
    {
        ret = InsertBST(&bst, array[i]);
    }

    printf("最小值为%d\n", MinBST(&bst));
    printf("最大值为%d\n", MaxBST(&bst));

    printf("遍历\n");
    TraversalBST(&bst);
    printf("\n");

    BST_Node *p = SearchBST(&bst, 258);
    if( NULL != p )
        printf("查找的节点的值为%d\n", p->data);
    else
        printf("查找的节点不存在\n");

    printf("删除59\n");
    DeleteBST(&bst, 59);
    printf("遍历\n");
    TraversalBST(&bst);
    printf("\n删除69\n");
    DeleteBST(&bst, 69);
    printf("遍历\n");
    TraversalBST(&bst);

    DestroyBST(&bst);

    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值