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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章