• <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>
            對于一般的二叉樹來說,刪去樹中的一個結(jié)點是沒有意義的,因為它將使以被刪除的結(jié)點為根的子樹變成森林,破壞了整棵樹的結(jié)構(gòu)
            但是,對于二叉排序樹,刪去樹上的一個結(jié)點相當于刪去有序序列中的一個記錄,只要在刪除某個結(jié)點后不改變二叉排序樹的特性即可。
            ??????在二叉排序樹上刪除一個結(jié)點的算法如下:
            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有左子樹,找到其左子樹的最右邊的葉子結(jié)點r,用該葉子結(jié)點r來替代p,把r的左孩子
            作為r的父親的右孩子。
            2。若p沒有左子樹,直接用p的右孩子取代它。

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


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

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

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

            ????????????free(r);
            ????????????return?p;
            ??????}
            ??????else
            ??????{
            ????????????btree?*q?=?p->rchild;???//q指向其右子樹;
            ????????????free(p);
            ????????????return?q;
            ??????}
            }
            Posted on 2006-06-04 16:52 夢想飛揚 閱讀(1975) 評論(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
            二叉排序樹刪除節(jié)點
            Status DeleteBST(BiTree &T, Keytype key,Bitree f) //引進f為T的父節(jié)點
            {
            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; // 利用二叉排序樹的前驅(qū)后繼直觀圖幫助理解
            } //探索p的直接前驅(qū),最后得到其為s(s->lchild==NULL).
            p->data = s->data; //覆蓋,容易理解
            if(q==p) // while未執(zhí)行,有s=p->rchild,s覆蓋p,s位置由s->rchild占據(jù).
            q->rchild = s->rchild;  
            else        //   未執(zhí)行else前有,q->lchild=s;
            q->lchild = s->rchild; 
            free(s);
            }

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

            }

            欧美精品丝袜久久久中文字幕| 亚洲国产精品无码久久久蜜芽| 久久综合中文字幕| 久久久久无码中| 久久亚洲精品国产精品| 精品久久久久久无码国产| 国产69精品久久久久久人妻精品| 国产精品久久久久影视不卡| 理论片午午伦夜理片久久| 国产亚洲欧美成人久久片| 亚洲精品视频久久久| 久久综合九色综合欧美狠狠| 一本久久a久久精品vr综合| 国产激情久久久久影院| 久久永久免费人妻精品下载| 色综合久久夜色精品国产| 久久婷婷国产麻豆91天堂| 久久精品中文闷骚内射| 久久夜色精品国产亚洲| 要久久爱在线免费观看| 久久最近最新中文字幕大全| 久久精品国产亚洲AV麻豆网站| 久久亚洲AV成人无码| 久久天天躁狠狠躁夜夜av浪潮| 中文字幕久久欲求不满| 久久青青草原国产精品免费| 97超级碰碰碰久久久久| 婷婷久久久亚洲欧洲日产国码AV| 性做久久久久久久久| 亚洲精品视频久久久| 免费精品久久久久久中文字幕| 久久久久国产亚洲AV麻豆| 欧美伊香蕉久久综合类网站| 精品午夜久久福利大片| 久久99国产精品99久久| 久久夜色tv网站| 国产精品免费久久久久影院 | 国产亚洲精品自在久久| 久久人人爽人人爽人人爽| 囯产精品久久久久久久久蜜桃| 亚洲狠狠婷婷综合久久蜜芽|