查找之二叉排序樹

二叉排序樹或者是一棵空樹,或者是具備下列性質的二叉樹
    1)若左子樹不空,則左子樹上全部結點的值均小於或等於它的根結點的值;
    2)若右子樹不空,則右子樹上全部結點的值均小於或等於它的根結點的值;
    3)左、右子樹也分別爲二叉排序樹;
查找步驟:
    若根結點的關鍵字值等於查找的關鍵字,成功;
    不然,若小於根結點的關鍵字值,遞歸查左子樹。
    若大於根結點的關鍵字值,遞歸查右子樹。
    若子樹爲空,查找不成功。
簡介:
    二叉排序樹一般採用二叉鏈表做爲存儲結構。中序遍歷二叉排序樹可獲得一個依據關鍵字的有序
序列,一個無序序列能夠經過構造一棵二叉排序樹變成一個有序序列,構造樹的過程便是對無序序列
進行排序的過程。每次插入的新的結點都是二叉排序樹上新的葉子結點,在進行插入操做,沒必要移動
其餘結點,只需改動某個結點的指針,由空變爲非空便可。搜索、插入、刪除的時間複雜度等於樹高
,指望O(logn),最壞就是O(n);
定義結構:
    /* 二叉樹的二叉鏈表結點結構定義 */
    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 TURE;
        }
        else
            return FALSE; /*  樹中已有關鍵字相同的結點,再也不插入 */
    }
二叉排序樹的刪除算法
    在二叉排序樹中刪去一個結點,分三種狀況:
    1.若 *p結點爲葉子結點,即PL(左子樹)和PR(右子樹)均爲空樹。因爲刪去葉子結點
    不破壞整棵樹的結構,則只需修改其雙親結點的指針便可。
    2.若 *p結點只有左子樹PL或右子樹PR,此時只要令PL或PR直接成爲其雙親結點*f的
    左子樹(當*p是左子樹)或右子樹(當*p是右子樹)便可,作此修改也不破壞二叉排序
    樹的特性。
    3.若*p結點的左子樹和右子樹均不空。在刪去*P以後,爲保持其餘元素之間的相對位置
    不變,可按中序遍歷保持有序進行調整。比較好的作法是,找到*p的直接前驅(或後繼
    )*s,用*s來替換結點*p,而後再刪除結點*s;
    /* 若二叉排序樹T中存在關鍵字等於key的數據元素,則刪除該數據元素結點 */
    /* 並返回TRUE;不然返回FALSE */
    Status DeleteBSD(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);
        }
    }
    /* 從二叉排序樹中刪除結點p,並重接它的左或右子樹 */
    Status Delete(BiTree *p)
    {
        BiTree q,s;
        if((*p)->rchild == NULL)//右子樹空則只需重接它的左子樹(待刪結點是葉子也走此分支)
        {
            q = *p;
            *p=(*p)->lchild;
            free(q);
            q= NULL;
        }
        else if((*p)->lchild == NULL)//只需重接它的右子樹
        {
            q = *p;
            *p = (*p)->rchild;
            free(q);
            q= NULL;
        }
        else   //左右子樹均不空
        {
            q = *p;
            s = (*p)->lchild;
            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);
            s = NULL;
        }
        return TRUE;
    }算法

相關文章
相關標籤/搜索