算法:查找--3--平衡二叉树(AVL树)

其他链接
C++原版本
另一版本
本文参考大话数据结构,注意书中有部分错误:勘误表

平衡二叉树:是一种二叉排序树,其中每个结点的左子树和右子树的高度差至多等于1。
AVL:是两位俄罗斯数学家名字的简称:G.M.Adelson-Velskii和E.M.Landis

AVL是一种高度平衡的二叉排序树。
要么它是一棵空树,要么它的左子树和右子树都是平衡二叉树,切左子树和右子树的深度之差的绝对值不超过1。

将二叉树上结点的左子树深度减去右子树深度的值称为平衡因子BF(Balance Factor),那么平衡二叉树上所有结点的平衡因子只可能是-1,、0、1。只要有一个结点的平衡因子的绝对值大于1,该二叉树就是不平衡的。

AVLTree源码:只有插入功能(也可以用于创建),查找和二叉排序树代码一样。
删除功能未实现(等等吧)。

public class BitNode
{
    public int data;
    public int bf; 	//平衡因子
    public BitNode leftChild;
    public BitNode rightChild;
}
public class AVLTree
{
    const int LH = 1;
    const int EH = 0;
    const int RH = -1;

    public BitNode head = null;
    private bool taller = false;

    public bool InsertNode(int key)
    {
        return InsertAVL(ref head, key);
    }

    /// <summary>
    /// 若在平衡的二叉排序树T中不存在和e有相同关键字的结点,则插入一个
    /// 数据元素为e的新结点并返回1,否则返回0,若因插入而使二叉排序树
    /// 失去平衡,则作平衡旋转处理,布尔变量taller反映T的长高与否
    /// 注:********这里需要添加ref修饰,不加ref当传参为null时,改变不了传参前的对象********
    /// </summary>
    /// <param name="T"></param>
    /// <param name="e"></param>
    /// <param name="taller"></param>
    /// <returns></returns>
    private bool InsertAVL(ref BitNode T, int e)
    {
        if (head == null)
        {
            head = new BitNode();
            head.data = e;
            head.bf = 0;
            head.leftChild = null;
            head.rightChild = null;
            taller = true;
            return true;
        }

        if (T == null)
        {
            //插入新结点,树“长高”,置taller为true
            T = new BitNode();
            T.data = e;
            T.leftChild = T.rightChild = null;
            T.bf = EH;
            taller = true;
        }
        else
        {
            if (e == T.data)
            {
                //树中已存在和e有相同关键字的结点则不再插入
                taller = false;
                return false;
            }

            if (e < T.data)
            {
                //应继续在T的左子树中进行搜索                
                if (!InsertAVL(ref T.leftChild, e)) //未插入
                {
                    return false;
                }

                if (taller)  //已插入到T的左子树中且左子树“长高”
                {
                    switch (T.bf)   //检查T的平衡度
                    {
                        case LH:    //原本左子树比右子树高,需要作平衡处理
                            LeftBalance(ref T);
                            taller = false;
                            break;
                        case EH:    //原本左右子树等高,现因左子树增高而树增高
                            T.bf = LH;
                            taller = true;
                            break;
                        case RH:    //原本右子树比左子树高,现在左右子树等高
                            T.bf = EH;
                            taller = false;
                            break;
                    }
                }
            }
            else
            {
                //应继续在T的右子树中进行搜索
                if (!InsertAVL(ref T.rightChild, e))    //未插入
                {
                    return false;
                }

                if (taller) //已插入到T的右子树且右子树“长高”
                {
                    switch (T.bf)   //检查T的平衡度
                    {
                        case LH:    //原本左子树比右子树高,现在左右子树等高
                            T.bf = EH;
                            taller = false;
                            break;
                        case EH:    //原本左右子树等高,现因右子树增高而树增高
                            T.bf = RH;
                            taller = true;
                            break;
                        case RH:    //原本右子树比左子树高,需要作平衡处理
                            RightBalance(ref T);
                            taller = false;
                            break;
                    }
                }
            }
        }
        return true;
    }

    /// <summary>
    /// 对以T所指结点为根的二叉树作左平衡旋转处理
    /// 算法结束时,T指向新的根结点
    /// </summary>
    /// <param name="T"></param>
    private void LeftBalance(ref BitNode T)
    {
        BitNode left;
        BitNode leftNodeRrightChild;
        left = T.leftChild;
        switch (left.bf)
        {
            //检查T的左子树的平衡度,并作相应平衡处理
            case LH://新结点插入在T的左孩子的左子树上,要作单右旋处理
                T.bf = left.bf = EH;
                RightRotate(ref T);
                break;
            case RH://新结点插入在T的左孩子的右子树上,要作双旋处理
                leftNodeRrightChild = left.rightChild;  //leftNodeRrightChild指向T的左孩子的右子树根
                switch (leftNodeRrightChild.bf)         //修改T及其左孩子的平衡因子
                {
                    case LH:
                        T.bf = RH;
                        left.bf = EH;
                        break;
                    case EH:
                        T.bf = left.bf = EH;
                        break;
                    case RH:
                        T.bf = EH;
                        left.bf = LH;
                        break;
                }
                leftNodeRrightChild.bf = EH;
                LeftRotate(ref T.leftChild);
                RightRotate(ref T);
                break;
        }
    }

    private void RightBalance(ref BitNode T)
    {
        BitNode right;
        BitNode rightNodeLeftChild;
        right = T.rightChild;
        switch (right.bf)
        {
            //检查T的右子树的平衡度,并作相应平衡处理
            case RH://新结点插入在T的右孩子的右子树上,要作单左旋处理
                T.bf = right.bf = EH;
                LeftRotate(ref T);
                break;
            case LH://新结点插入在T的右孩子的左子树上,要作双旋处理
                rightNodeLeftChild = right.leftChild;  //rightNodeLeftChild指向T的右孩子的左子树根
                switch (rightNodeLeftChild.bf)         //修改T及其右孩子的平衡因子
                {
                    case LH:
                        T.bf = EH;
                        right.bf = RH;
                        break;
                    case EH:
                        T.bf = right.bf = EH;
                        break;
                    case RH:
                        T.bf = LH;
                        right.bf = EH;
                        break;
                }
                rightNodeLeftChild.bf = EH;
                RightRotate(ref T.rightChild);
                LeftRotate(ref T);
                break;
        }
    }

    /// <summary>
    /// 右旋:对以node为根的二叉排序树作右旋处理
    /// 处理之后node指向新的树根结点,即旋转处理之前的左子树的根结点
    /// </summary>
    /// <param name="node"></param>
    private void RightRotate(ref BitNode node)
    {
        BitNode temp = node.leftChild;        
        node.leftChild = temp.rightChild;
        temp.rightChild = node;
        node = temp;
    }

    /// <summary>
    /// 左旋:对以node为根的二叉排序树作左旋处理
    /// 处理之后node指向新的树根结点,即旋转处理之前的右子树的根结点0
    /// </summary>
    /// <param name="node"></param>
    private void LeftRotate(ref BitNode node)
    {
        BitNode temp = node.rightChild;
        node.rightChild = temp.leftChild;
        temp.leftChild = node;
        node = temp;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值