大話數據結構學習筆記 - 查找之二叉排序樹(Binary Sort Tree)及其C實現

大話數據結構學習筆記 - 查找之二叉排序樹(Binary Sort Tree)及其C實現

二叉排序樹

Search_Binary_Search_Tree

二叉排序樹(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, BiTNode *f, BiTNode **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)
{
    BiTNode *p, *s;
    if(!SearchBST(*T, key, NULL, &p))  /* 查找不成功 */
    {
        s = CreateBiTNode(key);
        if(!p)
            *T = s;  /* 插入 s 爲新的根節點 */
        else if(key < p->data)
            p->lchild = s;  /* 插入 s 爲左孩子 */
        else
            p->rchild = s;  /* 插入 s 爲右孩子 */
        return TRUE;
    }
    return FALSE;  /* 樹中已有關鍵字相同的結點, 不再插入 */
}

刪除

/*
 * 從二叉排序樹中刪除節點 p, 並重接它的左或右子樹
 */
Status Delete(BiTNode **p)
{
    BiTNode *q, *s;
    if((*p)->lchild == NULL)  /* 若右子樹爲空,則只需重接它的左子樹 */
    {
        q = *p;
        *p = (*p)->rchild;
        free(q);
    }
    else if((*p)->rchild == NULL)  /* 若左子樹爲空,則只需重接它的右子樹 */
    {
        q = *p;
        *p = (*p)->lchild;
        free(q);
    }
    else  /* 左右子樹均不空 */
    {
        q = *p;
        s = (*p)->lchild;  /* s 爲其左子樹 */
        while(s->rchild)   /* 轉左,尋找其左子樹最右結點, 即尋找待刪結點的前驅 */
        {
            q = s;
            s = s->rchild;
        }
        (*p)->data = s->data;  /* s 指向被刪結點的直接前驅 */
        if(q != (*p))
            q->rchild = s->lchild;  /* 重接 q 的右子樹 */
        else
            q->lchild = s->lchild;  /* 重接 q 的左子樹 */
        free(s);
    }
    return TRUE;
}

/*
 * 若二叉排序樹 T 中存在關鍵字等於 key 的數據元素時, 則刪除該數據元素結點, 並返回 TRUE; 否則返回 FALSE.
 */
Status DeleteBST(BiTree *T, int key)
{
    if(!(*T))       /* 不存在關鍵字等於 key 的數據元素 */
        return FALSE;
    else if(key == (*T)->data)    /* 找到關鍵字等於 key 的數據元素 */
        return Delete(T);
    else if(key < (*T)->data)
        return DeleteBST(&(*T)->lchild, key);
    else
        return DeleteBST(&(*T)->rchild, key);
}

複雜度

Search_Binary_Search_Tree_time_complexity

若二叉排序樹比較平衡,即其深度與完全二叉樹相同,均爲log2n+1 ,類似於上圖左圖 那麼查找的時間複雜度就爲O(logn) , 近似於折半查找。若插入序列以排好序,則最壞情況類似於上圖右圖,時間複雜度爲O(n) , 等同於順序查找。

代碼

Binary Search Tree

結語

如上複雜度分析,二叉排序樹的超照性能取決於二叉排序樹的形狀,但其形狀不確定,取決於輸入序列。如何構建一個平衡的二叉排序樹呢?請看下節文章 平衡二叉樹

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