高度平衡树(AVL)

高度平衡树,又称 平衡二叉树。由Adelse-Velskil和Landis在1962年提出的高度平衡的二叉树,简称AVL树。

AVL结点

因为树的旋转,结点的高度可改变,需要重新定义结点的高等属性。

/// <summary>
/// AVL结点
/// </summary>
public class AVLNode<T> : BTNode<T> where T : IComparable<T>
{
    /// <summary>
    /// 当前结点的高度
    /// </summary>
    public new int Height { get; set; }
    /// <summary>
    /// 当前父结点
    /// </summary>
    public new AVLNode<T> Parent
    {
        get { return (AVLNode<T>)base.Parent; }
        set { base.Parent = value; }
    }
    /// <summary>
    /// 左子结点
    /// </summary>
    public new AVLNode<T> LeftChild
    {
        get { return (AVLNode<T>)base.LeftChild; }
        set { base.LeftChild = value; }
    }
    /// <summary>
    /// 右子结点
    /// </summary>
    public new AVLNode<T> RightChild
    {
        get { return (AVLNode<T>)base.RightChild; }
        set { base.RightChild = value; }
    }

    public AVLNode() : base() { }
    public AVLNode(T value) : base(value) { }

    public AVLNode(T value, int height, AVLNode<T> parent, AVLNode<T> left, AVLNode<T> right) : base(value, parent, left, right)
    {
        Height = height;
    }
}

实现

public class AVLTree<T> : BinarySearchTree<T> where T : IComparable<T>
{
    /// <summary>
    /// 返回根结点
    /// </summary>
    public new AVLNode<T> Root
    {
        get { return (AVLNode<T>)base.Root; }
        internal set { base.Root = value; }
    }

    public AVLTree() : base() { }

    /// <summary>
    /// 在树中插入元素
    /// </summary>
    /// <param name="item">插入项</param>
    public override void Insert(T item)
    {
        var node = new AVLNode<T>() { Data = item };
        if (InsertNode(node))
        {
            RebalanceTreeAt(node);
        }
        else
        {
            throw new InvalidOperationException("树不允许插入重复元素" + item.ToString());
        }
    }

    /// <summary>
    /// 从树中删除元素
    /// </summary>
    public override void Remove(T item)
    {
        if (IsEmpty)
        {
            throw new Exception("树是空的");
        }
        var node = FindNode(Root, item);
        if (Remove(node))
        {
            RebalanceTreeAt((AVLNode<T>)node);
        }
        else
        {
            throw new Exception("找不到元素项" + item.ToString());
        }
    }
    // TODO
}

在插入结点的过程中,会破坏AVL树的特性,旋转原则如下:

左-左型:做右旋;


右-右型:做左旋转;


左-右型:先做左旋,后做右旋;


右-左型:先做右旋,再做左旋;

其他具体实现,同学们可根据AVL的特点,自行补充完善。

应用



public void Test()
{
    var bst = new BinarySearchTree<int>();
    int[] values = new int[] { 11, 7, 15, 6, 5, 4, 3, 2 };
    bst.Insert(values);

    WsCommFunc.ConsoleWriteLine(bst.ToString(TraversalMode.LevelOrder));
    Console.WriteLine(TreeDrawer.DrawTree(bst));
    Console.WriteLine("BST退化为线性。。。。。。改为AVL树");


    var avl = new AVLTree<int>();
    values = new int[] { 5, 4, 6, 3, 2 };
    bst.Clear();
    bst.Insert(values);
    Console.WriteLine(TreeDrawer.DrawTree(bst));
    Console.WriteLine("Ex1. 左-左型,右旋......");
    avl.Clear();
    avl.Insert(values);
    WsCommFunc.ConsoleWriteLine(TreeDrawer.DrawTree(avl));

    values = new int[] { 9, 7, 12, 6, 8, 5 };
    bst.Clear();
    bst.Insert(values);
    Console.WriteLine(TreeDrawer.DrawTree(bst));
    Console.WriteLine("Ex2. 左-左型,右旋......");
    avl.Clear();
    avl.Insert(values);
    WsCommFunc.ConsoleWriteLine(TreeDrawer.DrawTree(avl));


    values = new int[] { 8, 7, 10, 9, 13, 14};
    bst.Clear();
    bst.Insert(values);
    Console.WriteLine(TreeDrawer.DrawTree(bst));
    Console.WriteLine("Ex3. 右-右型,左旋......");
    avl.Clear();
    avl.Insert(values);
    WsCommFunc.ConsoleWriteLine(TreeDrawer.DrawTree(avl));


    values = new int[] { 8, 7 };
    avl.Clear();
    avl.Insert(values);
    Console.WriteLine("Ex4. 原始树");
    Console.WriteLine(TreeDrawer.DrawTree(avl));
    Console.WriteLine("插入 6, 右旋");
    avl.Insert(6);
    Console.WriteLine(TreeDrawer.DrawTree(avl));
    Console.WriteLine("插入 9");
    avl.Insert(9);
    Console.WriteLine(TreeDrawer.DrawTree(avl));
    Console.WriteLine("插入 10, 左旋");
    avl.Insert(10);
    Console.WriteLine(TreeDrawer.DrawTree(avl));
    Console.WriteLine("插入 11, 左旋");
    avl.Insert(11);
    Console.WriteLine(TreeDrawer.DrawTree(avl));
    Console.WriteLine("插入 12, 左旋");
    avl.Insert(12);
    Console.WriteLine(TreeDrawer.DrawTree(avl));
    Console.WriteLine("插入 15");
    avl.Insert(15);
    Console.WriteLine(TreeDrawer.DrawTree(avl));
    Console.WriteLine("插入 14,先右旋,再左旋");
    avl.Insert(14);
    Console.WriteLine(TreeDrawer.DrawTree(avl));
    Console.WriteLine("删除最大值 15");
    avl.RemoveMax();    //avl.Remove(15);
    Console.WriteLine(TreeDrawer.DrawTree(avl));
    Console.WriteLine("插入 13,先左旋,再右旋");
    avl.Insert(13);
    Console.WriteLine(TreeDrawer.DrawTree(avl));

}
原文地址:https://www.cnblogs.com/wesson2019-blog/p/15021580.html