数据结构复习之平衡二叉树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
*/
时间: 2024-12-21 11:05:55

数据结构复习之平衡二叉树AVL删除的相关文章

数据结构复习之平衡二叉树AVL插入

平衡二叉树(Balancedbinary tree)是由阿德尔森-维尔斯和兰迪斯(Adelson-Velskiiand Landis)于1962年首先提出的,所以又称为AVL树. 定义:平衡二叉树或为空树,或为如下性质的二叉排序树: (1)左右子树深度之差的绝对值不超过1; (2)左右子树仍然为平衡二叉树. 平衡二叉树可以避免排序二叉树深度上的极度恶化,使树的高度维持在O(logn)来提高检索效率. 因为插入节点导致整个二叉树失去平衡分成如下的四种情况: 假设由于在二叉排序树上插入节点而失去平衡

数据结构快速回顾——平衡二叉树 AVL (转)

平衡二叉树(Balanced Binary Tree)是二叉查找树的一个进化体,也是第一个引入平衡概念的二叉树.1962年,G.M. Adelson-Velsky 和 E.M. Landis发明了这棵树,所以它又叫AVL树.平衡二叉树要求对于每一个节点来说,它的左右子树的高度之差不能超过1,如果插入或者删除一个节点使得高度之差大于1,就要进行节点之间的旋转,将二叉树重新维持在一个平衡状态.这个方案很好的解决了二叉查找树退化成链表的问题,把插入,查找,删除的时间复杂度最好情况和最坏情况都维持在O(

java数据结构与算法之平衡二叉树(AVL树)的设计与实现

[版权申明]未经博主同意,不允许转载!(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/53892797 出自[zejian的博客] 关联文章: java数据结构与算法之顺序表与链表设计与实现分析 java数据结构与算法之双链表设计与实现 java数据结构与算法之改良顺序表与双链表类似ArrayList和LinkedList(带Iterator迭代器与fast-fail机制) java数据结构与算法之栈(Stack)设

7. 蛤蟆的数据结构进阶七平衡二叉树

7. 蛤蟆的数据结构进阶七平衡二叉树 本地名言:"金钱的贪求(这个毛病,目前我们大家都犯得很凶)和享乐的贪求,促使我们成为它们的奴隶,也可以说,把我们整个身心投入深渊.唯利是图,是一种痼疾,使人卑鄙,但贪求享乐,更是一种使人极端无耻,不可救药的毛病. --郎加纳斯" 我们来看下传说中的平衡二叉树,为什么说他传说中呢?因为蛤蟆接触ORACLE数据库比较多,而ORACLE数据中用到最多的索引就是平衡二叉树,所以嘛. 欢迎转载,转载请标明出处:http://write.blog.csdn.n

图解平衡二叉树,AVL树(一)

图解平衡二叉树,AVL树(一) 学习过了二叉查找树,想必大家有遇到一个问题.例如,将一个数组{1,2,3,4}依次插入树的时候,形成了图1的情况.有建立树与没建立树对于数据的增删查改已经没有了任何帮助,反而增添了维护的成本.而只有建立的树如图2,才能够最大地体现二叉树的优点. 在上述的例子中,图2就是一棵平衡二叉树.科学家们提出平衡二叉树,就是为了让树的查找性能得到最大的体现(至少我是这样理解的,欢迎批评改正).下面进入今天的正题,平衡二叉树. AVL的定义 平衡二叉查找树:简称平衡二叉树.由前

数据结构复习之--“插入排序”-JAVA实现

菜鸟中的菜鸟一枚,面临找工作,复习下数据结构,写的插入排序算法记录一下,每天写一点,不断积累吧! import java.util.Scanner; /** * * @author DL * 数据结构复习之插入排序练习程序 * */ public class SortTest { public static void main(String [] args){ Scanner sc = new Scanner(System.in); int totalNums = sc.nextInt();//

平衡二叉树 AVL 的插入节点后旋转方法分析

平衡二叉树 AVL( 发明者为Adel'son-Vel'skii 和 Landis)是一种二叉排序树,其中每一个节点的左子树和右子树的高度差至多等于1. 首先我们知道,当插入一个节点,从此插入点到树根节点路径上的所有节点的平衡都可能被打破,如何解决这个问题呢? 这里不讲大多数书上提的什么平衡因子,什么最小不平衡子树,实际上让人(me)更加费解.实际上你首要做的就是先找到第一个出现不平衡的节点,也就是高度最高的那个节点A,对以它为根的子树做一次旋转或者两次旋转,此时这个节点的平衡问题解决了,整个往

数据结构 平衡二叉树avl c++

平衡二叉树:一颗空树,或者是具有以下性质的二叉树 左子树和右子树都是平衡二叉树 左子树和右子树的深度只差不超过1 把二叉树节点的平衡因子BF(Balance Factor)定义为该节点的左子树深度减去右子树深度,则平衡二叉树所有结点的平衡因子只能是-1,0,1.只要有一个结点的平衡因子绝对值大于一就是不平衡的: 平衡二叉树的构造 对二叉树结点做一下定义,bf用来记录结点的平衡因子 1 typedef struct BSTNode{ 2 int val; 3 int bf; 4 struct BS

数据结构【查找】—平衡二叉树AVL

/*自己看了半天也没看懂代码,下次再补充说明*/ 解释: 平衡二叉树(Self-Balancing Binary Search Tree 或Height-Balanced Binary Search Tree),是一种二叉排序树,其中每一个节点的左子树和右子树的高度差至多等于1. 实现原理: 平衡二叉树构建的基本思想就是在构建二又排序树的过程中,每当插入一个结点时,先检查是否因插入而破坏了树的平衡性,若是,则找出最小不平衡子树.在保持二又排序树特性的前提下,调整最小不平衡子树中各结点之间的链接关