二叉搜索树

目录

1.什么是二叉搜索树?

2.二叉搜索树的查找

2.1尾递归

2.2非尾递归

3.查找最大和最小元素 

3.1尾递归

3.2非尾递归 

4.二叉搜索树的插入

5.二叉搜索树的删除


1.什么是二叉搜索树?

二叉搜索树(BST,Binary Search Tree), 也称二叉排序树二叉查找树

二叉搜索树:一棵二叉树,可以为空;如果不为空,满足以下性质:

        1. 非空左子树的所有键值小于其根结点的键值。

        2. 非空右子树的所有键值大于其根结点的键值。

        3. 左、右子树都是二叉搜索树。 

二叉搜索树操作的特别函数:

        Position Find( ElementType X, BinTree BST ):从二叉搜索树BST 中查找元素X,返回其所在结点的地址;

        Position FindMin( BinTree BST ):从二叉搜索树BST中查找并返回 最小元素所在结点的地址;

        Position FindMax( BinTree BST ) :从二叉搜索树BST中查找并返回 最大元素所在结点的地址。

        BinTree Insert( ElementType X, BinTree BST )

        BinTree Delete( ElementType X, BinTree BST ) 

2.二叉搜索树的查找

查找从根结点开始,如果树为空,返回NULL

若搜索树非空,则根结点关键字和X进行比较,并进行不同处理:

         若X小于根结点键值,只需在左子树中继续搜索;

         如果X大于根结点的键值,在右子树中进行继续搜索;

         若两者比较结果是相等,搜索完成,返回指向此结点的指针。 

2.1尾递归

Position Find( ElementType X, BinTree BST )
{
    if( !BST ) return NULL; /*查找失败*/
    if( X > BST->Data )
     return Find( X, BST->Right ); /*在右子树中继续查找*/
    else if( X < BST->Data )
     return Find( X, BST->Left ); /*在左子树中继续查找*/
    else /* X == BST->Data */
     return BST; /*查找成功,返回结点的找到结点的地址*/
}

2.2非尾递归

 由于非递归函数的执行效率高,可将“尾递归”函数改为迭代函数

Position IterFind( ElementType X, BinTree BST )
{
 while( BST ) {
     if( X > BST->Data )
         BST = BST->Right; /*向右子树中移动,继续查找*/
     else if( X < BST->Data )
         BST = BST->Left; /*向左子树中移动,继续查找*/
     else /* X == BST->Data */
         return BST; /*查找成功,返回结点的找到结点的地址*/
 }
     return NULL; /*查找失败*/
}

3.查找最大和最小元素 

最大元素一定是在树的最右分枝的端结点上

最小元素一定是在树的最左分枝的端结点上 

3.1尾递归

Position FindMin( BinTree BST )
{
     if( !BST ) return NULL; /*空的二叉搜索树,返回NULL*/
     else if( !BST->Left )
         return BST; /*找到最左叶结点并返回*/
     else
         return FindMin( BST->Left ); /*沿左分支继续查找*/
}
Position FindMax( BinTree BST, Position max )
{
    if( !BST ) return max; /* 空的二叉搜索树,返回当前最大值 */
    else if( !BST->Right )
        return BST; /* 找到最右叶结点并返回 */
    else
        return FindMax( BST->Right, BST->Right ); /* 沿右分支继续查找 */
}

3.2非尾递归 

Position FindMin(BinTree BST)
{
    while (BST && BST->Left)
        BST = BST->Left;
    /* 沿左分支继续查找,直到最左叶结点 */
    return BST;
}
Position FindMax( BinTree BST )
{
     if(BST )
         while( BST->Right ) BST = BST->Right;
         /*沿右分支继续查找,直到最右叶结点*/
     return BST;
} 

4.二叉搜索树的插入

关键是要找到元素应该插入的位置, 可以采用与查找类似的方法

/* 插入函数 */
BinTree Insert(ElementType X, BinTree BST) {
    if (!BST) {
        /* 如果树为空,生成并返回一个新的节点 */
        BST = malloc(sizeof(struct TreeNode));
        if (BST == NULL) {
            fprintf(stderr, "Out of memory!\n");
            exit(1);
        }
        BST->Data = X;
        BST->Left = BST->Right = NULL;
    } else if (X < BST->Data) {
        /* 递归插入到左子树 */
        BST->Left = Insert(X, BST->Left);
    } else if (X > BST->Data) {
        /* 递归插入到右子树 */
        BST->Right = Insert(X, BST->Right);
    }
    /* 如果X已经存在于树中,什么都不做 */
    return BST;
}

5.二叉搜索树的删除

 考虑三种情况:

一.        要删除的是叶结点:直接删除,并再修改其父结点指针---置为NULL

〖例〗:删除 35 

二.        要删除的结点只有一个孩子结点: 将其父结点的指针指向要删除结点的孩子结点

〖例〗:删除 33

三.        要删除的结点有左、右两棵子树: 用另一结点替代被删除结点:右子树的最小元素 或者 左子树的最大元素

 〖例〗:删除 41

/* 删除函数 */
BinTree Delete(ElementType X, BinTree BST) {
    Position Tmp;

    if (!BST) {
        printf("要删除的元素未找到\n");
    } else if (X < BST->Data) {
        /* 左子树递归删除 */
        BST->Left = Delete(X, BST->Left);
    } else if (X > BST->Data) {
        /* 右子树递归删除 */
        BST->Right = Delete(X, BST->Right);
    } else {
        /* 找到要删除的结点 */
        if (BST->Left && BST->Right) {
            /* 被删除结点有左右两个子结点 */
            Tmp = FindMin(BST->Right);
            /* 在右子树中找最小的元素填充删除结点 */
            BST->Data = Tmp->Data;
            /* 在删除结点的右子树中删除最小元素 */
            BST->Right = Delete(BST->Data, BST->Right);
        } else {
            /* 被删除结点有一个或无子结点 */
            Tmp = BST;
            if (!BST->Left) {
                /* 有右孩子或无子结点 */
                BST = BST->Right;
            } else if (!BST->Right) {
                /* 有左孩子或无子结点 */
                BST = BST->Left;
            }
            free(Tmp);
        }
    }
    return BST;
}

 完整代码示例

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

/* 定义二叉树节点结构体 */
struct TreeNode {
    int Data;
    struct TreeNode *Left;
    struct TreeNode *Right;
};

typedef struct TreeNode* BinTree;
typedef struct TreeNode* Position;
typedef int ElementType;

/* 查找函数(递归) */
Position Find(ElementType X, BinTree BST) {
    if (!BST) {
        return NULL;
    } else if (X < BST->Data) {
        return Find(X, BST->Left);
    } else if (X > BST->Data) {
        return Find(X, BST->Right);
    } else {
        return BST;
    }
}

/* 查找函数(迭代) */
Position FindIterative(ElementType X, BinTree BST) {
    while (BST) {
        if (X < BST->Data) {
            BST = BST->Left;
        } else if (X > BST->Data) {
            BST = BST->Right;
        } else {
            return BST;
        }
    }
    return NULL;
}

/* 查找最小值节点 */
Position FindMin(BinTree BST) {
    while (BST && BST->Left)
        BST = BST->Left;
    return BST;
}

/* 插入函数 */
BinTree Insert(ElementType X, BinTree BST) {
    if (!BST) {
        BST = malloc(sizeof(struct TreeNode));
        if (BST == NULL) {
            fprintf(stderr, "内存分配失败!\n");
            exit(1);
        }
        BST->Data = X;
        BST->Left = BST->Right = NULL;
    } else if (X < BST->Data) {
        BST->Left = Insert(X, BST->Left);
    } else if (X > BST->Data) {
        BST->Right = Insert(X, BST->Right);
    }
    return BST;
}

/* 删除函数 */
BinTree Delete(ElementType X, BinTree BST) {
    Position Tmp;
    if (!BST) {
        printf("要删除的元素未找到\n");
    } else if (X < BST->Data) {
        BST->Left = Delete(X, BST->Left);
    } else if (X > BST->Data) {
        BST->Right = Delete(X, BST->Right);
    } else {
        if (BST->Left && BST->Right) {
            Tmp = FindMin(BST->Right);
            BST->Data = Tmp->Data;
            BST->Right = Delete(BST->Data, BST->Right);
        } else {
            Tmp = BST;
            if (!BST->Left) {
                BST = BST->Right;
            } else if (!BST->Right) {
                BST = BST->Left;
            }
            free(Tmp);
        }
    }
    return BST;
}

/* 打印树(中序遍历) */
void PrintTree(BinTree BST) {
    if (BST != NULL) {
        PrintTree(BST->Left);
        printf("%d ", BST->Data);
        PrintTree(BST->Right);
    }
}

/* 主函数,测试各种操作 */
int main() {
    BinTree tree = NULL;

    /* 插入节点 */
    tree = Insert(10, tree);
    tree = Insert(5, tree);
    tree = Insert(15, tree);
    tree = Insert(3, tree);
    tree = Insert(7, tree);
    tree = Insert(12, tree);
    tree = Insert(18, tree);

    printf("插入节点后的树(中序遍历):");
    PrintTree(tree);
    printf("\n");

    /* 查找节点 */
    Position foundNode = Find(7, tree);
    if (foundNode) {
        printf("递归查找,找到节点值为:%d\n", foundNode->Data);
    } else {
        printf("递归查找,节点值为7未找到。\n");
    }

    foundNode = FindIterative(12, tree);
    if (foundNode) {
        printf("迭代查找,找到节点值为:%d\n", foundNode->Data);
    } else {
        printf("迭代查找,节点值为12未找到。\n");
    }

    /* 删除节点 */
    tree = Delete(10, tree);
    printf("删除10后的树(中序遍历):");
    PrintTree(tree);
    printf("\n");

    tree = Delete(5, tree);
    printf("删除5后的树(中序遍历):");
    PrintTree(tree);
    printf("\n");

    /* 再次插入和删除以验证 */
    tree = Insert(10, tree);
    tree = Insert(5, tree);
    tree = Insert(20, tree);
    printf("重新插入后的树(中序遍历):");
    PrintTree(tree);
    printf("\n");

    tree = Delete(14, tree);
    printf("尝试删除14(未找到)的树(中序遍历):");
    PrintTree(tree);
    printf("\n");

    /* 结束 */
    return 0;
}

 示例结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值