二叉排序樹的查找、插入和刪除

二叉排序樹(Binary Sort Tree)又稱爲二叉查找樹,它或者是一棵空樹,或者是具有下列性質的二叉樹:
– 若它的左子樹不爲空,則左子樹上所有結點的值均小於它的根節點的值;
– 若它的右子樹不爲空,則右子樹上所有結點的值均大於它的根節點的值;
– 它的左、右子樹也分別爲二叉排序樹(遞歸)。

在這裏插入圖片描述
二叉排序樹用中序遍歷之後即爲順序數組;
查找:

// 二叉樹的二叉鏈表結點結構定義
typedef struct BiTNode
{
    int data;
    struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;

// 遞歸查找二叉排序樹 T 中是否存在 key
// 指針 f 指向 T 的雙親,其初始值調用值爲 NULL
// 若查找成功,則指針 p 指向該數據元素結點,並返回 TRUE
// 否則指針 p 指向查找路徑上訪問的最後一個結點,並返回 FALSE
Status SearchBST(BiTree T, int key, BiTree f, BiTree *p)
{
    if( !T )    // 查找不成功
    {
        *p = f;
        return FALSE;
    }
    else if( key == T->data )   // 查找成功
    {
        *p = T;
        return TRUE;
    }
    else if( key < T->data )
    {
        return SearchBST( T->lchild, key, T, p );   // 在左子樹繼續查找
    }
    else
    {
        return SearchBST( T->rchild, key, T, p );   // 在右子樹繼續查找
    }
}

插入:

// 當二叉排序樹 T 中不存在關鍵字等於 key 的數據元素時,
// 插入 key 並返回 TRUE,否則返回 FALSE
Status InsertBST(BiTree *T, int key)
{
    BiTree p, s;
    if( !SearchBST(*T, key, NULL, &p) )
    {
        s = (BiTree)malloc(sizeof(BiTNode));
        s->data = key;
        s->lchild = s->rchild = NULL;
        
        if( !p )       
        {
            *T = s;     // 插入 s 爲新的根結點
        }
        else if( key < p->data )
        {
            p->lchild = s;  // 插入 s 爲左孩子
        }
        else
        {
            p->rchild = s;  // 插入 s 爲右孩子
        }
        return TRUE;
    }
    else
    {
        return FALSE;   // 樹中已有關鍵字相同的結點,不再插入
    }
}

刪除:

Status DeleteBST(BiTree *T, int key)
{
    if( !*T )
    {
        return FALSE;
    }
    else
    {
        if( key == (*T)->data )
        {
            return Delete(T);
        }
        else if( key < (*T)->data )
        {
            return DeleteBST(&(*T)->lchild, key);
        }
        else
        {
            return DeleteBST(&(*T)->rchild, key);
        }
    }
}

Status Delete(BiTree *p)
{
    BiTree q, s;
    
    if( (*p)->rchild == NULL ) //需要刪除的節點沒有右子樹時,直接用該節點的左子樹覆蓋該節點
    {
        q = *p;//q用來記錄需要刪除的節點
        *p = (*p)->lchild;
        free(q);
    }
    else if( (*p)->lchild == NULL )//需要刪除的節點沒有左子樹時,直接用該節點的左子樹覆蓋該節點
    {
        q = *p;
        *p = (*p)->rchild;
        free(q);
    }
    else//需要刪除的節點既有左子樹又有右子樹時,可用其前驅節點A的值替換該節點的值,並用其前驅節點A的左子樹覆蓋節點A
    {
        q = *p; //q用來記錄其前驅節點的雙親節點
        s = (*p)->lchild;
        
        while( s->rchild )
        {
            q = s;
            s = s->rchild;
        }
        
        (*p)->data = s->data;
        
        if( q != *p )
        {
            q->rchild = s->lchild;
        }
        else
        {
            q->lchild = s->lchild;
        }
        
        free(s);
    }
    
    return TRUE;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章