6. 树--二叉搜索树

二叉搜索树

二叉搜索树(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)

二叉搜索树的查找操作:Find

  • 查找跟结点开始,如果树为空,返回NULL
  • 若搜索树非空,则根结点关键字和X进行比较,并进行不同处理:
    1. 若X小于根结点键值,只需在左子树中继续搜索
    2. 若X大于根结点键值,在右子树中进行继续搜索
    3. 若两者比较结果是相等,搜索完成,返回指向此结点的指针

递归实现

Position Find(ElementType X, BinTree BST) {
    if (NULL == BST)    // 此时搜索树为空,返回NULL
        return NULL;

    if (X > BST->Data)        // 在右子树中继续查找
        return Find(X, BST->Right);

    if (X < BST->Data)
        return Find(X, BST->Left);  // 在左子树中继续查找

    return BST;                     // 查找成功,返回结点指针
}

迭代实现

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

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

    return NULL;        // 查找失败
}

查找的效率决定于树的高度

查找最大和最小元素

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

image

实现

查找最小元素的递归函数

Position FindMin(BinTree BST) {
    if (BST == NULL)    // 空的二叉搜索树,返回NULL
        return NULL;

    if (BST->Left == NULL)      // 找到最左叶结点并返回
        return BST;

    return FindMin(BST->Left);  // 沿最左分枝继续查找
}

查找最大元素的迭代函数

Position FindMax(BinTree BST) {
    if (BST != NULL) {
        While (BST->Right != NULL)  // 沿最右分枝继续查找,直到最右叶结点
            BST = BST->Right;
    }

    return BST;
}

二叉搜索树的插入

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

实现

BinTree Insert(ElementType X, BInTree BST) {
    if (BST == NULL) {  // 若原树为空,生成并返回一个结点的二叉搜索树
        BST = malloc(sizeof(struct TreeNode));
        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;
}

二叉树搜索树的删除

需要考虑三种情况:
* 要删除的是叶结点:直接删除,并修改其父结点指针—置为NULL
* 要删除的结点只有一个孩子结点:将其父结点的指针指向要删除结点的孩子结点
* 要删除的结点有左右两棵子树:用另一结点替代被删除的结点
* 右子树的最小元素
* 左子树的最大元素

实现

BinTree Delete(ElementType X, BinTree BST) {
    Position Tmp;
    if (BST == NULL) {
        printf(要删除的元素未找到);
        return NULL;
    }

    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 != NULL && BST->Right != NULL) {  // 被删除结点有左右两个子结点
            Tmp = FindMin(BST->Right);  // 在右子树中找最小元素填充删除结点
            BST->Data = Tmp->Data;
            BST->Right = Delete(BST->Data, BST->Right); // 在删除结点的右子树中删除最小元素
        } else {    // 被删除结点有一个或无子结点
            Tmp = BST;
            if (BST->Left == NULL)  // 有右孩子或无子结点
                BST = BST->Right;
            else if (BST->Right == NULL)   // 有左孩子或无子结点
                BST = BST->Left;
            free(Tmp);
        }
    }

    return BST;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章