• <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 夢想飛揚 閱讀(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
            二叉排序樹刪除節點
            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老熟妇色| 国产精品免费久久久久影院| 精品久久久久久国产免费了| 无码8090精品久久一区| 伊人久久综合精品无码AV专区| 国产成人无码久久久精品一| 久久亚洲av无码精品浪潮| 久久精品毛片免费观看| 一97日本道伊人久久综合影院| 国产精品久久久久久久久免费| 久久笫一福利免费导航| 中文字幕一区二区三区久久网站 | 99久久人妻无码精品系列| 久久人人爽人人澡人人高潮AV| 亚洲午夜久久久影院伊人| 久久人人超碰精品CAOPOREN| 精品久久久久久中文字幕人妻最新| 性做久久久久久免费观看| 欧美久久综合性欧美| 日韩人妻无码一区二区三区久久 | 国产伊人久久| 国产精品一久久香蕉产线看| 久久精品国产男包| 久久无码AV中文出轨人妻| 免费一级做a爰片久久毛片潮| 久久这里只有精品首页| 国产精品9999久久久久| 99久久99久久精品免费看蜜桃| 亚洲色欲久久久综合网| 无码八A片人妻少妇久久| 麻豆久久久9性大片| 99久久国产精品免费一区二区| 伊人久久大香线蕉综合热线| 亚洲精品NV久久久久久久久久| 伊人久久大香线蕉无码麻豆| 亚洲精品无码专区久久同性男| 久久久久久国产a免费观看黄色大片 | 亚洲国产成人精品91久久久 | 国产精品18久久久久久vr | 欧美日韩中文字幕久久久不卡|