• <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 夢想飛揚 閱讀(1968) 評論(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);
            }

            }

            成人久久精品一区二区三区| 久久久久国产精品麻豆AR影院 | 日韩欧美亚洲综合久久 | 国产精品一区二区久久精品涩爱| 国产精品日韩深夜福利久久| 青青草原综合久久大伊人导航| 免费精品久久久久久中文字幕| 亚洲人成网站999久久久综合 | 91精品免费久久久久久久久| 久久久精品人妻无码专区不卡| 狠狠综合久久AV一区二区三区| 国内精品伊人久久久久av一坑 | 久久精品成人欧美大片| 日韩人妻无码精品久久免费一| 天天久久狠狠色综合| 久久只这里是精品66| 久久久国产乱子伦精品作者| 欧美久久一区二区三区| 2022年国产精品久久久久| 亚洲精品乱码久久久久久蜜桃| 日韩亚洲国产综合久久久| 久久久精品免费国产四虎| 久久人人爽人人精品视频| 国产精品久久久久a影院| 91亚洲国产成人久久精品| 亚洲国产精品无码久久久蜜芽| 国产亚洲色婷婷久久99精品91| 亚洲国产一成人久久精品| 日韩AV毛片精品久久久| 色综合久久天天综合| 国产亚洲精久久久久久无码| 性做久久久久久久久老女人| 久久这里只有精品久久| 久久超乳爆乳中文字幕| 久久亚洲中文字幕精品有坂深雪| 性做久久久久久久久| 久久久久99精品成人片三人毛片 | 久久久久久无码Av成人影院| 中文字幕久久波多野结衣av| 久久笫一福利免费导航| 久久无码专区国产精品发布|