中序二叉排序删除结点的官场哲学

二叉排序树是动态查找树,其定义是二叉排序树或者是空树,或者是具有下列性质的二叉树:1)若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;2)若它的右子树不为空,则右子树上所有结点的值均大于它的根结点的值;3)它的左,右子树也分别是二叉排序树。

今天讨论一下中序二叉排序树中删除一个结点。删除一个结点,要求剩下的树也是中序二叉排序树。分三种情况,1)若删除的是叶结点,删就删了,只要把其父结点相应的指针指向向null。2)若删除的结点只有一个左子树或只有一个右子树,也简单,把父结点的指针指向被删除结点的左或右结点。3)被删除结点有左右两个子树,这个最复杂了。我们假设删除结点为D,数据结构书上谈到两种方法,一个叫上提法,把删除结点的左孩子(设此结点叫L)提升到删除结点D的位置,若删除结点D有右子树(设此结点叫R),则R挂在L结点后,让D在右分支上一直滑到底。方法二是替代法,原理是用删除结点的前驱替代。步骤是自删除结点D出发,先左走一步,然后一直向右到底,找到删除结点的前驱(设为P),用P来取代删除结点D的位置,若P有左子树,设为PL(注:因为已经向右到底了,所以P不可能有右子树),则把PL放在P的父结点右指针下。

猛然发现中序二叉排序树及其删除就是描述官场升迁的情景啊!

二叉排序树就是一个官位从高到低的结构,现在有一个贪官D,滥用职权,以权谋私,被革职了,D的职位要有人来代替。怎么找人代替呢,两个方案,一个是让D的下属顶上,另一方法是通过选举,找一个能力(不是贪污能力)比其还强一些的来替代(不能找强太多的,把领导的光芒都盖了可不件好事),有多少能力干多少事。

我们先看方案一,让D的下属顶上。D的下属有两个一个L,一个R,我们中国自古有个尊左的礼节,左为贵,L和D平时走的更近一些,所以让L顶上,可L也不见得是好鸟,也许怕R把自己的把柄抖出来,上台后就开始大清洗,排挤D的旧手下R及其部下,L通过各种手段把R以及R的部下安排到最差职位,我们说过左为贵,右自然成了差的地方,R和R的部下就在L掌握的官位体系中的一路右滑右滑,终于有一天滑到底了。这场纷争就此告一段落。官场凶险,人心险恶,腥风血雨暗藏其中,江湖恩怨稍触及发。

再来看方案二,民主选举,这可是人心所向啊。都说深藏不露,但是是金子总会发光的,我们终于找到比D能力强一些的P了,方法是先尊左,左表示什么呢,表示好,右表示差,正如上面提到的,找到后,不能再往左了,为什么呢,左是好呀,我们需要找个能力只比D强一点的,注意是一点啊,好不容易强一点后就得拐到差了,行,向右拐吧,顺着右走到最下边,一白胡子老头身着蓑衣头戴斗笠,手握三丈长的鱼杆,正在钓鱼,鱼杆上没有鱼钩,这能钓个null啊,就是他了,这也印证了干活的人还是最底层的人啊。白胡子老头叫P,P上任后,好人啊(底层人民是单纯善良的),没有清洗,还是沿用D原来的班底,不过也说回来了,一个底层的人提上来,自己的亲信都没有,还没实力搞清洗。再看看P的原手下PL,P只有一个手下,是靠左边的(因为我们是走到最右发见P的,也就是说P是最右边的了),那PL的日子怎么样呢,PL的日子也是不错的,P走后,P的原领导PPL提升到P的位子了,不提升就少一个人干活了。大家都其乐融融,所以说嘛,还是民主的好。

好了,博各位一笑,上面的只是为了让大家能更容易记往中序二叉排序树的删除算法。

下面是一中序二叉排序树删除结点的算法:

方案1-左孩子提升:

        void Delete(BSTNode d)
        {
            if (d.Right == null)//只有左子树
            {
                d = d.Left;
            }
            else if (d.Left == null)//只有右子树
            {
                d = d.Right;
            }
            else//有左右子树
            {
                BSTNode l = d.Left;
                BSTNode r = d.Right;

                BSTNode rb = l;//最右下的结点,沉到最底使用
                while (rb.Right != null)
                {
                    rb = rb.Right; 
                }

                //d被l替换
                d.Value = l.Value;
                d.Left = l.Left;
                d.Right = l.Right;

                rb.Right = r;//d原来的右子树沉到最右下
            }
        }
 
方案2-前驱代替:
        void Delete(BSTNode d)
        {
            if (d.Right == null)//只有左子树
            {
                d = d.Left;
            }
            else if (d.Left == null)//只有右子树
            {
                d = d.Right;
            }
            else//有左右子树
            {
                BSTNode l = d.Left;
                BSTNode pp = d;//pp是p的父结点
                BSTNode p = l;//p在下面会是向左后最右下的结点
                while (p.Right != null)//遍历到最右下
                {
                    pp = p;
                    p = p.Right;
                }

                d.Value = p.Value;

                if (d != pp)//右d的左孩子有右子树,把最pp的右指针指向p的左孩子
                {
                    pp.Right = p.Left;
                }
                else//右d的左孩子没有右子树,把p提升到d的位置
                {
                    d.Left = p.Left;
                }                 
            }
        }
删除二叉排序树中一结点,方法有很多,只要保持删除后仍然有序即可。
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值