当前位置: 首页 > news >正文

平衡二叉树AVL删除

平衡二叉树的插入过程: http://www.cnblogs.com/hujunzheng/p/4665451.html

对于二叉平衡树的删除采用的是二叉排序树删除的思路:

  假设被删结点是*p,其双亲是*f,不失一般性,设*p是*f的左孩子,下面分三种情况讨论:
⑴ 若结点*p是叶子结点,则只需修改其双亲结点*f的指针即可。
⑵ 若结点*p只有左子树PL或者只有右子树PR,则只要使PL或PR 成为其双亲结点的左子树即可。
⑶ 若结点*p的左、右子树均非空,先找到*p的中序前趋结点*s(注意*s是*p的左子树中的最右下的结点,它的右链域为空),然后有两种做法:
① 令*p的左子树直接链到*p的双亲结点*f的左链上,而*p的右子树链到*p的中序前趋结点*s的右链上。
② 以*p的中序前趋结点*s代替*p(即把*s的数据复制到*p中),将*s的左子树链到*s的双亲结点*q的左(或右)链上。

注:leftBalance_del 和 rightBalance_del方法是在删除节点时对左子树和右子树的平衡调整,leftBalance 和 rightBalance方法是在插入节点是对左右子树的平衡调整。 在具体调整的时候,和插入式调整时运用同样的分类方法,这里介绍一种情况,如下图所示(代码部分见代码中的提示)

 

 

复制代码
#include<iostream>
#include<cstring>
#include<string>
#include<queue>
#include<map>
#include<cstdio>
#define LH 1 //左高 
#define EH 0 //等高 
#define RH -1 //右高 
using namespace std;

template <typename ElemType>
class BSTNode{
    public:
        ElemType data;//节点的数据 
        int bf;//节点的平衡因子
        BSTNode *child[2];
        BSTNode(){
            child[0] = NULL;
            child[1] = NULL;
        }
};

typedef BSTNode<string> BSTnode, *BSTree;

template <typename ElemType>
class AVL{
    public:
        BSTNode<ElemType> *T;
        void buildT();
        void outT(BSTNode<ElemType> *T);
        void deleteAVL(BSTNode<ElemType>* &T, ElemType key, bool &shorter);
        bool insertAVL(BSTNode<ElemType>* &T, ElemType key, bool &taller); 
    private:
        void deleteNode(BSTNode<ElemType>* T, BSTNode<ElemType>* &s, BSTNode<ElemType>* p, bool flag, bool &shorter);
        void rotateT(BSTNode<ElemType>* &o, int x);//子树的左旋或者右旋
        void leftBalance(BSTNode<ElemType>* &o);
        void rightBalance(BSTNode<ElemType>* &o);
        
        void leftBalance_del(BSTNode<ElemType>* &o);
        void rightBalance_del(BSTNode<ElemType>* &o);
};

template <typename ElemType>
void AVL<ElemType>::rotateT(BSTNode<ElemType>* &o, int x){
    BSTNode<ElemType>* k = o->child[x^1];
    o->child[x^1] = k->child[x];
    k->child[x] = o;
    o = k; 
}

template <typename ElemType>
void AVL<ElemType>::outT(BSTNode<ElemType> *T){
    if(!T) return;
    cout<<T->data<<" ";
    outT(T->child[0]);
    outT(T->child[1]);
}

template <typename ElemType>
void AVL<ElemType>::buildT(){
   T = NULL;
   ElemType key;
   while(cin>>key){
           if(key==0) break;
           bool taller = false;
           insertAVL(T, key, taller);
   }
}

template <typename ElemType>
void AVL<ElemType>::deleteNode(BSTNode<ElemType>* T, BSTNode<ElemType>* &s, BSTNode<ElemType>* p, bool flag, bool &shorter){
    if(flag){
        flag = false;
        deleteNode(T, s->child[0], s, flag, shorter);
        if(shorter){
            switch(s->bf){
                case LH:
                    s->bf = EH;
                    shorter = false;
                    break; 
                case EH:
                    s->bf = RH;
                    shorter = true;
                    break; 
                case RH:
                    rightBalance_del(s);
                    shorter = false;
                    break;
            }
        }
    } else {
        if(s->child[1]==NULL){
            T->data = s->data;
            BSTNode<ElemType>* ss = s; 
            if(p != T){
                p->child[1] = s->child[0];
            } else {
                p->child[0] = s->child[0];
            }
            delete ss;//s是引用类型,不能delete s 
            shorter = true; 
            return ;
        }
        deleteNode(T, s->child[1], s, flag, shorter);
        if(shorter){
            switch(s->bf){
                case LH://这是上面配图的情况
                    leftBalance_del(s);
                    shorter = false; 
                    break; 
                case EH:
                    s->bf = LH;
                    shorter = true;
                    break; 
                case RH:
                    s->bf = EH;
                    shorter = false;
                    break;
            }
        } 
    }
} 

template <typename ElemType>
bool AVL<ElemType>::insertAVL(BSTNode<ElemType>* &T, ElemType key, bool &taller){
    if(!T){//插入新的节点,taller=true 那么树的高度增加 
        T = new BSTNode<ElemType>();
        T->data = key;
        T->bf = EH;
        taller = true;
    } else {
        if(T->data == key){
            taller = false;
            return false;
        }
        if(T->data > key){//向T的左子树进行搜索并插入 
            if(!insertAVL(T->child[0], key, taller)) return false;
            if(taller){//
                switch(T->bf){
                    case LH://此时左子树的高度高,左子树上又插入了一个节点,失衡,需要进行调整 
                        leftBalance(T);
                        taller = false;//调整之后高度平衡 
                        break; 
                    case EH:
                        T->bf = LH;
                        taller = true;
                        break; 
                    case RH:
                        T->bf = EH;
                        taller = false;                        
                        break;
                }
            }
        } 
        if(T->data < key) {//向T的右子树进行搜索并插入 
            if(!insertAVL(T->child[1], key, taller)) return false;
            switch(T->bf){
                case LH:
                    T->bf = EH;
                    taller = false; 
                    break; 
                case EH:
                    T->bf = RH;
                    taller = true;
                    break; 
                case RH:
                    rightBalance(T);    
                    taller = false;                    
                    break;
            }
        }
    }
    return true;
}


template <typename ElemType>
void AVL<ElemType>::deleteAVL(BSTNode<ElemType>* &T, ElemType key, bool &shorter){
    if(T->data == key){
        BSTNode<ElemType>*q, s; 
        if(!T->child[1]){//右子树为空,然后重接其左子树 
            q = T;
            T = T->child[0];
            shorter = true;//树变矮了 
            delete q;
        } else if(!T->child[0]){//左子树为空,重接其右子树 
            q = T;
            T = T->child[1];
            shorter = true;//树变矮了 
            delete q;
        } else {//左右子树都非空 ,也就是第三种情况 
            deleteNode(T, T, NULL, true, shorter);
            shorter = true;
        } 
    } else if(T->data > key) {//左子树 
        deleteAVL(T->child[0], key, shorter);
        if(shorter){
            switch(T->bf){
                case LH:
                    T->bf = EH; 
                    shorter = false;
                    break;
                case RH:
                    rightBalance_del(T);
                    shorter = false;
                    break;
                case EH:
                    T->bf = RH;
                    shorter = true;
                    break;
            }
        }
    } else if(T->data < key){//右子树 
        deleteAVL(T->child[1], key, shorter);
        if(shorter){
            switch(T->bf){
                case LH://这是上面配图的情况
                    leftBalance_del(T);
                    shorter = false;
break;
case RH: T->bf = EH; shorter = false; break; case EH: T->bf = LH; shorter = true; break; } } } } template <typename ElemType> void AVL<ElemType>::leftBalance(BSTNode<ElemType>* &T){ BSTNode<ElemType>* lchild = T->child[0]; switch(lchild->bf){//检查T的左子树的平衡度,并作相应的平衡处理 case LH://新节点 插入到 T的左孩子的左子树上,需要对T节点做单旋(右旋)处理 T->bf = lchild->bf = EH; rotateT(T, 1); break; case RH://新节点 插入到 T的左孩子的右子树上,需要做双旋处理 1.对lchild节点进行左旋,2.对T节点进行右旋 BSTNode<ElemType>* rdchild = lchild->child[1]; switch(rdchild->bf){//修改 T 及其左孩子的平衡因子 case LH: T->bf = RH; lchild->bf = EH; break; case EH: T->bf = lchild->bf = EH; break;//发生这种情况只能是 rdchild无孩子节点 case RH: T->bf = EH; lchild->bf = LH; break; } rdchild->bf = EH; rotateT(T->child[0], 0);//不要写成 rotateT(lc, 0);//这样的话T->lchild不会改变 rotateT(T, 1); break; } } template <typename ElemType> void AVL<ElemType>::rightBalance(BSTNode<ElemType>* &T){ BSTNode<ElemType>* rchild = T->child[1]; switch(rchild->bf){//检查T的左子树的平衡度,并作相应的平衡处理 case RH://新节点 插入到 T的右孩子的右子树上,需要对T节点做单旋(左旋)处理 T->bf = rchild->bf = EH; rotateT(T, 0); break; case LH://新节点 插入到 T的右孩子的左子树上,需要做双旋处理 1.对rchild节点进行右旋,2.对T节点进行左旋 BSTNode<ElemType>* ldchild = rchild->child[0]; switch(ldchild->bf){//修改 T 及其右孩子的平衡因子 case LH: T->bf = EH; rchild->bf = RH; break; case EH: T->bf = rchild->bf = EH; break;//发生这种情况只能是 ldchild无孩子节点 case RH: T->bf = LH; rchild->bf = EH; break; } ldchild->bf = EH; rotateT(T->child[1], 1); rotateT(T, 0); break; } } template <typename ElemType> void AVL<ElemType>::leftBalance_del(BSTNode<ElemType>* &T){ BSTNode<ElemType>* lchild = T->child[0]; switch(lchild->bf){ case LH: T->bf = EH; lchild->bf = EH; rotateT(T, 1); break; case EH: T->bf = LH; lchild->bf = EH; rotateT(T, 1); break; case RH://这是上面配图的情况 BSTNode<ElemType>* rdchild = lchild->child[1]; switch(rdchild->bf){ case LH: T->bf = RH; lchild->bf = rdchild->bf = EH; break; case EH: rdchild->bf = T->bf = lchild->bf = EH; break; case RH: T->bf = rdchild->bf = EH; lchild->bf = LH; break; } rotateT(T->child[0], 0); rotateT(T, 1); break; } } template <typename ElemType> void AVL<ElemType>::rightBalance_del(BSTNode<ElemType>* &T){ BSTNode<ElemType>* rchild = T->child[1]; BSTNode<ElemType>* ldchild = rchild->child[0]; switch(rchild->bf){ case LH: switch(ldchild->bf){ case LH: ldchild->bf = T->bf = EH; rchild->bf = RH; break; case EH: ldchild->bf = T->bf = rchild->bf = EH; break; case RH: rchild->bf = T->bf = EH; ldchild->bf = LH; break; } rotateT(T->child[1], 1); rotateT(T, 0); break; case EH: //outT(this->T);e EH: T->bf = RH; rchild->bf = EH; rotateT(T, 0); break; case RH: T->bf = EH; rchild->bf = EH; rotateT(T, 0); break; } } int main(){ AVL<int> avl; avl.buildT(); cout<<"平衡二叉树先序遍历如下:"<<endl; avl.outT(avl.T); cout<<endl; bool shorter = false; avl.deleteAVL(avl.T, 24, shorter); avl.outT(avl.T); return 0; } /* 13 24 37 90 53 0 13 24 37 90 53 12 26 0 */









本文转自 小眼儿 博客园博客,原文链接:http://www.cnblogs.com/hujunzheng/p/4669058.html,如需转载请自行联系原作者

相关文章:

  • Excel\Word\PPT - Shape内容获取方式
  • SQL SERVER 分布式事务(DTC)
  • (转)http协议
  • 如何安全设定和检测你的密码安全性?
  • FreeRADIUS 负载均衡和高可用
  • .net 4.0发布后不能正常显示图片问题
  • Liferay 模板文件的解析
  • 艾伟:[原创]谈谈WCF中的Data Contract(2):WCF Data Contract对Generic的支持
  • NeHe OpenGL第三十四课:地形
  • ansible-playbook批量部署zabbix
  • 艾伟_转载:C#来创建和读取XML文档
  • 一例HP ADG数据恢复成功(8×73GB SCSI)
  • 艾伟_转载:LINQ to SQL、NHibernate比较(二)-- LINQ to SQL实例
  • php经典面试题
  • JavaScript控制图片横向滚动代码
  • Docker 笔记(1):介绍、镜像、容器及其基本操作
  • iOS仿今日头条、壁纸应用、筛选分类、三方微博、颜色填充等源码
  • java中的hashCode
  • web标准化(下)
  • XML已死 ?
  • 阿里云应用高可用服务公测发布
  • 基于Android乐音识别(2)
  • 基于web的全景—— Pannellum小试
  • 面试遇到的一些题
  • 批量截取pdf文件
  • 算法之不定期更新(一)(2018-04-12)
  • 腾讯优测优分享 | 你是否体验过Android手机插入耳机后仍外放的尴尬?
  • 通过npm或yarn自动生成vue组件
  • 通过来模仿稀土掘金个人页面的布局来学习使用CoordinatorLayout
  • 我建了一个叫Hello World的项目
  • 用jQuery怎么做到前后端分离
  • 优秀架构师必须掌握的架构思维
  • No resource identifier found for attribute,RxJava之zip操作符
  • ​MPV,汽车产品里一个特殊品类的进化过程
  • # 日期待t_最值得等的SUV奥迪Q9:空间比MPV还大,或搭4.0T,香
  • # 手柄编程_北通阿修罗3动手评:一款兼具功能、操控性的电竞手柄
  • $.extend({},旧的,新的);合并对象,后面的覆盖前面的
  • (3)选择元素——(14)接触DOM元素(Accessing DOM elements)
  • (二)斐波那契Fabonacci函数
  • (附源码)流浪动物保护平台的设计与实现 毕业设计 161154
  • (力扣)1314.矩阵区域和
  • (三)elasticsearch 源码之启动流程分析
  • (三分钟)速览传统边缘检测算子
  • (四)docker:为mysql和java jar运行环境创建同一网络,容器互联
  • (原創) 如何使用ISO C++讀寫BMP圖檔? (C/C++) (Image Processing)
  • (转)GCC在C语言中内嵌汇编 asm __volatile__
  • (转)mysql使用Navicat 导出和导入数据库
  • (转)VC++中ondraw在什么时候调用的
  • .gitignore文件---让git自动忽略指定文件
  • .NET 4.0中使用内存映射文件实现进程通讯
  • .NET CLR基本术语
  • .net core 6 集成 elasticsearch 并 使用分词器
  • .net core 调用c dll_用C++生成一个简单的DLL文件VS2008
  • .NET gRPC 和RESTful简单对比
  • .NET/C# 利用 Walterlv.WeakEvents 高性能地中转一个自定义的弱事件(可让任意 CLR 事件成为弱事件)