二叉搜索樹

什麼是二叉搜索樹

二叉搜索樹(BST)也稱爲二叉排序樹或二叉查找樹。

二叉搜索樹:一棵二叉樹,可以爲空;如果不爲空,滿足以下性質。

  • 非空左子樹的鍵值小於其根結點的鍵值。
  • 非空右子樹的鍵值大於其根結點的鍵值。
  • 左右子樹都是二叉搜索樹。

二叉搜索樹的查找操作

查找從根結點開始,如果樹爲空,返回NULL。

若樹非空,則根結點關鍵字和X進行比較,並進行處理:

  • 若X小於根結點的值,只需要在左子樹中繼續搜索。
  • 若X大於根結點的值,在右子樹中繼續搜索。
  • 若兩者比較結果相等,搜索完成,返回指向此結點的指針。

圖示

Position Find ( ElementType X, BinTree BST )
{
    if( !BST ) return NULL;//查找失敗
    if( X > BST->Data )//如果X大於根結點的值,到右子樹中查找
        return Find( X, BST->Right );
    else if ( X < BST->Data )//否則,在左子樹中查找
        return Find( X, BST->Left );
    else//如果相等,則查找成功,返回結點的地址
        return BST;
}

上述代碼是用尾遞歸(在程序分支的最後進行遞歸),效率不高。從編譯的角度講,尾遞歸都是可以用循環來實現的。所以,可將尾遞歸改爲迭代函數。

Position IterFind( ElementType X, BinTree BST )
{
    while( BST ){
        if( X > BST->Data )
            BST=BST->Right;
        else if ( X < BST-> Data )
            BST=BST->Left;
        else
            return BST;
    }
    return NULL;
}

查找最大和最小值

最大元素一定是在樹的最右分支的端結點上 
最小元素一定是在樹的最左分支的端結點上

圖示

//查找最小值的遞歸算法
Position FindMin( BinTree BST )
{
    if( !BST ) return NULL;//空的二叉樹返回NULL
    if( !BST->Left ){//找到最左結點並返回
        return  BST;
    }else{//如果存在左孩子就繼續查找
        return FindMin( BST->Left );
    }
}

//查找最大值的迭代算法
Position FindMax( BinTree BST )
{
    if( BST )//一直向右查找
        while( BST->Right ) BST = BST->Right;
    return BST;
}

二叉搜索樹的插入

圖示

BinTree Insert( ElementType X, BinTree BST )
{
    if( !BST ){
        //若原樹爲空,則生成並返回一個節點的二叉樹
        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 );
        //else x存在,什麼也不做
        return BST;
    }
}

二叉搜索樹的刪除

有三種情況

  1. 要刪除的是葉結點:直接刪除,並修改其父結點指針—置爲NULL
  2. 要刪除的結點只有一個孩子結點:將其父結點的指針指向要刪除結點的孩子結點。
  3. 要刪除的結點有左、右兩棵子樹:用另一結點替代被刪除的結點:右子樹的最小元素,或者左子樹的最大元素。
BinTree Delete( ElementType X, BinTree BST )
{
    Position Tmp;
    if( !BST ) printf("要刪除的元素未找到");
    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
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章