平衡二叉树AVL插入

平衡二叉树(Balancedbinary tree)是由阿德尔森-维尔斯和兰迪斯(Adelson-Velskiiand Landis)于1962年首先提出的,所以又称为AVL树。

定义:平衡二叉树或为空树,或为如下性质的二叉排序树:

 (1)左右子树深度之差的绝对值不超过1;

 (2)左右子树仍然为平衡二叉树.

        平衡二叉树可以避免排序二叉树深度上的极度恶化,使树的高度维持在O(logn)来提高检索效率。

 

因为插入节点导致整个二叉树失去平衡分成如下的四种情况:

假设由于在二叉排序树上插入节点而失去平衡的最小子数根节点的指针为a(即a是离插入节点最近,且平衡因子绝对值超过1的祖先节点),则失去平衡后进行调整的规律如下:

1.如上图LL单向右旋处理:由于在*a的左子树根节点的左子树上插入节点,*a的平衡因子由1增至2,致使以*a为根节点的子树失去平衡,则需要进行一次向右的顺时针旋转操作。

2.如上图RR单向左旋处理:由于在*a的右子树根节点的右子树上插入节点, *a的平衡因子有-1变为-2,致使以*a为根节点的子树失去平衡,则学要进行一次向左的逆时针旋转操作。

3.如上图LR双向旋转(先左后右)处理:由于在*a的左子树根节点的右子树插入节点,*a的平衡因子有1增至2,致使以*a为根节点的子树失去平衡,则需要进行两次旋转(先左旋后右旋)操作。

4.如上图RL双向旋转(先右后左)处理:由于在*a的右子树根节点的左子树上插入节点,*a的平衡因子由-1变为-2,致使以*a为根节点的子树失去平衡,则需要进行两次旋转(先左旋后右旋)操作。

#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);
    private:
        bool insertAVL(BSTNode<ElemType>* &T, ElemType key, bool &taller);
        void rotateT(BSTNode<ElemType>* &o, int x);//子树的左旋或者右旋
        void leftBalance(BSTNode<ElemType>* &o);
        void rightBalance(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);
           outT(T);
           cout<<endl;
   }
}

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>::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;
    }
}

int main(){
    AVL<int> avl;
    avl.buildT();
    avl.outT(avl.T);
    return 0;
} 

/*
24 37 90 53 0
*/
时间: 2024-08-30 21:35:48

平衡二叉树AVL插入的相关文章

平衡二叉树AVL删除

平衡二叉树的插入过程: http://www.cnblogs.com/hujunzheng/p/4665451.html 对于二叉平衡树的删除采用的是二叉排序树删除的思路: 假设被删结点是*p,其双亲是*f,不失一般性,设*p是*f的左孩子,下面分三种情况讨论: ⑴ 若结点*p是叶子结点,则只需修改其双亲结点*f的指针即可. ⑵ 若结点*p只有左子树PL或者只有右子树PR,则只要使PL或PR 成为其双亲结点的左子树即可. ⑶ 若结点*p的左.右子树均非空,先找到*p的中序前趋结点*s(注意*s是

平衡二叉树(AVL)

此文是转载文章  平衡二叉树(Balanced binary tree)是由阿德尔森-维尔斯和兰迪斯(Adelson-Velskii and Landis)于1962年首先提出的,所以又称为AVL树. 定义:平衡二叉树或为空树,或为如下性质的二叉排序树:   (1)左右子树深度之差的绝对值不超过1;   (2)左右子树仍然为平衡二叉树.       平衡因子BF=左子树深度-右子树深度. 平衡二叉树每个结点的平衡因子只能是1,0,-1.若其绝对值超过1,则该二叉排序树就是不平衡的. 如图所示为平

网络子系统40_inet_peer平衡二叉树的插入

                                                                                                   // 遍历二叉树路径 // 宏的主要任务: // 1.遍历到达目标节点的路径 // 2.将路径上经过的节点保存在stack中 // 3.栈顶为peer_avl_empty // 4.stackptr指向下一个空闲的位置 1.2 #define lookup(_daddr,_stack) \ ({ \

平衡二叉树:php实现平衡二叉树(avl树)

<?phprequire 'bstorder.php';$test = range(1, 10);//$test = array(3,9,1,4,8,5,7,6,2,10);$tree = new bst($test, true);//$tree->deletenode('30');(非平衡树可删除,平衡树的没写删除操作)print_r($tree->gettree());?>bstorder.php<?php/*** php实现二叉排序树* @author zhaojian

平衡二叉树AVL操作模板_C 语言

复制代码 代码如下: /*** 目的:实现AVL* 利用数组对左右儿子简化代码,但是对脑力难度反而增大不少,只适合acm模板* 其实avl在acm中基本不用,基本被treap取代* avl一般只要求理解思路,不要求写出代码,因为真心很烦*/ #include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <string>#include <

软考考点---平衡二叉树

浅谈平衡二叉树           平衡二叉树(Balanced binarytree)是由阿德尔森-维尔斯和兰迪斯(Adelson-Velskii and Landis)于1962年首先提出的,所以又称为AVL树.           一.平衡二叉树的基本介绍           定义:平衡二叉树或为空树,或为如下性质的二叉排序树:         (1)左右子树深度之差的绝对值不超过1;         (2)左右子树仍然为平衡二叉树.         平衡因子BF=左子树深度-右子树深度.

C#实现二叉树查找删除插入

问题描述 C#实现二叉树查找删除插入 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication3 { class Node { private object _data; private Node left; private Node right; private Node _head; public int data; pr

我必须得告诉大家的MySQL优化原理

说起MySQL的查询优化,相信大家收藏了一堆奇淫技巧:不能使用 SELECT * .不使用NULL字段.合理创建索引.为字段选择合适的数据类型-.. 你是否真的理解这些优化技巧?是否理解其背后的工作原理?在实际场景下性能真有提升吗?我想未必.因而理解这些优化建议背后的原理就尤为重要,希望本文能让你重新审视这些优化建议,并在实际业务场景下合理的运用. MySQL逻辑架构 如果能在头脑中构建一幅MySQL各组件之间如何协同工作的架构图,有助于深入理解MySQL服务器.下图展示了MySQL的逻辑架构图

数据挖掘求职 | 想进BAT?先试试看这几道题!

从阿里数据分析师笔试看职业要求 以下试题是来自阿里巴巴招募实习生的一次笔试题,从笔试题的几个要求我们一起来看看数据分析的职业要求. 一.异常值是指什么?请列举1种识别连续型变量异常值的方法? 异常值(Outlier) 是指样本中的个别值,其数值明显偏离所属样本的其余观测值.在数理统计里一般是指一组观测值中与平均值的偏差超过两倍标准差的测定值. Grubbs' test(是以Frank E. Grubbs命名的),又叫maximum normed residual test,是一种用于单变量数据集