• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            對于一般的二叉樹來說,刪去樹中的一個結點是沒有意義的,因為它將使以被刪除的結點為根的子樹變成森林,破壞了整棵樹的結構
            但是,對于二叉排序樹,刪去樹上的一個結點相當于刪去有序序列中的一個記錄,只要在刪除某個結點后不改變二叉排序樹的特性即可。
            ??????在二叉排序樹上刪除一個結點的算法如下:
            btree?*?DeleteBST(btree?*b,?ElemType?x)
            {
            ??????if?(b)
            ??????{
            ????????????if?(b->data?==?x)
            ??????????????????b?=?DelNode(b);
            ????????????else?if?(b->data?>?x)
            ??????????????????b->lchild?=?DeleteBST(b->lchild,?x);
            ????????????else
            ??????????????????b->rchild?=?DeleteBST(b->rchild,?x);
            ??????}
            ??????return?b;
            }
            其中刪除過程有兩種方法。
            第一種過程如下:
            1。若p有左子樹,找到其左子樹的最右邊的葉子結點r,用該葉子結點r來替代p,把r的左孩子
            作為r的父親的右孩子。
            2。若p沒有左子樹,直接用p的右孩子取代它。

            第二種過程如下:
            1。若p有左子樹,用p的左孩子取代它;找到其左子樹的最右邊的葉子結點r,把p的右子樹作為r
            的右子樹。
            2。若p沒有左子樹,直接用p的右孩子取代它。
            ????兩種方法各有優劣,第一種操作簡單一點點,但均衡性不如第二種,因為它將結點p的右子樹
            全部移到左邊來了。下面將分別以兩種種思路編寫代碼。


            第一種:
            btree?*?DelNode(btree?*p)
            {
            ??????if?(p->lchild)
            ??????{
            ????????????btree?*r?=?p->lchild;???//r指向其左子樹;
            ????????while(r->rchild?!=?NULL)//搜索左子樹的最右邊的葉子結點r
            ????????{
            ????????????r?=?r->rchild;
            ????????}
            ????????????r->rchild?=?p->rchild;

            ????????????btree?*q?=?p->lchild;???//q指向其左子樹;
            ????????????free(p);
            ????????????return?q;
            ??????}
            ??????else
            ??????{
            ????????????btree?*q?=?p->rchild;???//q指向其右子樹;
            ????????????free(p);
            ????????????return?q;
            ??????}
            }

            第二種:
            btree?*?DelNode(btree?*p)
            {
            ??????if?(p->lchild)
            ??????{
            ????????????btree?*r?=?p->lchild;???//r指向其左子樹;
            ????????????btree?*prer?=?p->lchild;???//prer指向其左子樹;
            ????????while(r->rchild?!=?NULL)//搜索左子樹的最右邊的葉子結點r
            ????????{
            ??????????????????prer?=?r;
            ????????????r?=?r->rchild;
            ????????}

            ????????if(prer?!=?r)//若r不是p的左孩子,把r的左孩子作為r的父親的右孩子
            ????????{
            ??????????????????prer->rchild?=?r->lchild;
            ??????????????????r->lchild?=?p->lchild;?//被刪結點p的左子樹作為r的左子樹
            ????????????}
            ????????r->rchild?=?p->rchild;?//被刪結點p的右子樹作為r的右子樹

            ????????????free(p);
            ????????????return?r;
            ??????}
            ??????else
            ??????{
            ????????????btree?*q?=?p->rchild;???//q指向其右子樹;
            ????????????free(p);
            ????????????return?q;
            ??????}
            }
            ????但是上面這種方法,把r移來移去,很容易出錯,其實在這里我們刪除的只是p的元素值,而不是它的地址,所以完全沒有必要移動指針。仔細觀察,發現我們刪除的地址實際上是p的左子樹的最右邊的葉子結點r的地址,所以我們只要把r的數據填到p中,然后把r刪除即可。
            算法如下:
            btree?*?DelNode(btree?*p)
            {
            ??????if?(p->lchild)
            ??????{
            ????????????btree?*r?=?p->lchild;???//r指向其左子樹;
            ????????????btree?*prer?=?p->lchild;???//prer指向其左子樹;
            ????????while(r->rchild?!=?NULL)//搜索左子樹的最右邊的葉子結點r
            ????????{
            ??????????????????prer?=?r;
            ????????????r?=?r->rchild;
            ????????}
            ????????????p->data?=?r->data;

            ????????if(prer?!=?r)//若r不是p的左孩子,把r的左孩子作為r的父親的右孩子
            ??????????????????prer->rchild?=?r->lchild;
            ????????????else
            ????????????p->lchild?=?r->lchild;?//否則結點p的左子樹指向r的左子樹

            ????????????free(r);
            ????????????return?p;
            ??????}
            ??????else
            ??????{
            ????????????btree?*q?=?p->rchild;???//q指向其右子樹;
            ????????????free(p);
            ????????????return?q;
            ??????}
            }
            Posted on 2006-06-04 16:52 夢想飛揚 閱讀(1965) 評論(2)  編輯 收藏 引用

            Feedback

            # re: 二叉排序樹的刪除  回復  更多評論   

            2006-10-23 17:11 by coolaway
            btree * DeleteBST(btree *b, ElemType x)
            {
            if (b)
            if (x< b->data)
            DeleteBST(b->lchild, x);
            else if (x> b->data)
            DeleteBST(b->rchild, x);
            else if(b->lchild != null && b->rchild != null)
            {
            btree *temp = Min(b->rchild); // find the min key value in right child
            DeleteBST(temp,temp->data);
            }
            else
            {
            if(b->rchild == null) b=b->lchild;
            else if(b->lchild == null) b=b->rchild;
            }

            }

            # re: 二叉排序樹的刪除  回復  更多評論   

            2007-10-15 12:48 by csuzl
            二叉排序樹刪除節點
            Status DeleteBST(BiTree &T, Keytype key,Bitree f) //引進f為T的父節點
            {
            if(!T) return FALSE;
            else
            {
            if(EQ(key,T->data.key))
            return Delete(T,f);
            else
            if(LT(key,T->data.key))
            {
            f = T;
            return DeleteBST(T->lchild,key,f);
            }

            else
            {
            f = T;
            return DeleteBST(T->rchile,key);
            }

            }
            }

            Status Delete(Bitree &p,Bitree f)
            {
            if(!p->rchild)
            {
            if(p==f->lchild)
            f->lchild = p->lchild;
            else
            f->rchild = p->rchild;
            free(p);
            }
            else if(!p->lchild)
            {
            if(f->lchild==p)
            f->lchild = p->rchild;
            else
            f->rchild = p->rchild;
            free(q);
            }
            else
            {
            BiTree q = p,s = p->rchild;
            while(s->lchild)
            {
            q = s;
            s = s->lchild; // 利用二叉排序樹的前驅后繼直觀圖幫助理解
            } //探索p的直接前驅,最后得到其為s(s->lchild==NULL).
            p->data = s->data; //覆蓋,容易理解
            if(q==p) // while未執行,有s=p->rchild,s覆蓋p,s位置由s->rchild占據.
            q->rchild = s->rchild;  
            else        //   未執行else前有,q->lchild=s;
            q->lchild = s->rchild; 
            free(s);
            }

            最后else部分亦可更改為:
            else //利用直接前驅s替代p
            {
            BiTree q = p,s = p->lchild;
            while(s->rchild)
            {
            q = s;
            s = s->rchild;
            } //探索p的直接前驅,最后得到其前驅為s(s->rchild==NULL).
            p->data =s->data;
            if(q==p)
            q->lchild = s->lchild;
            else
            q->rchild = s->lchild;
            free(s);
            }

            }

            麻豆av久久av盛宴av| 国内精品久久国产| 久久亚洲精精品中文字幕| 日本久久久精品中文字幕| 久久婷婷午色综合夜啪| 中文字幕成人精品久久不卡 | 久久综合精品国产二区无码| 久久精品a亚洲国产v高清不卡| 一级做a爰片久久毛片看看| 色综合久久88色综合天天 | 综合久久国产九一剧情麻豆| 日韩中文久久| 色偷偷88欧美精品久久久 | 精品国产乱码久久久久久郑州公司| 久久狠狠一本精品综合网| 狠狠色丁香婷婷综合久久来 | 久久久久亚洲AV综合波多野结衣 | 色老头网站久久网| 狠色狠色狠狠色综合久久| 欧美亚洲国产精品久久高清| 日本道色综合久久影院| 蜜臀av性久久久久蜜臀aⅴ| 要久久爱在线免费观看| 91精品观看91久久久久久| 久久精品无码一区二区无码| 一本久久综合亚洲鲁鲁五月天亚洲欧美一区二区 | 久久久无码一区二区三区| 久久久国产打桩机| 伊人久久大香线蕉综合Av| 日本欧美国产精品第一页久久| 欧美一区二区精品久久| 国产精品久久波多野结衣| 成人亚洲欧美久久久久| 久久只有这精品99| 欧美久久久久久午夜精品| 狠狠色综合久久久久尤物| 久久久久久久精品妇女99| 久久亚洲中文字幕精品一区| 日本精品久久久久影院日本| 久久综合色区| 亚洲午夜久久久|