C#,自平衡二叉查找树(AVL Tree)的算法与源代码

C#,自平衡二叉查找树(AVL Tree)的算法与源代码_第1张图片

 G. M. Adelson-Velsky

一、AVL Tree 的历史

自平衡二叉查找树(AVL Tree)中任何节点的两个子树的高度最大差别为1,所以它也被称为高度平衡树。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。AVL树得名于它的发明者G. M. Adelson-Velsky和E. M. Landis,他们在1962年的论文《An algorithm for the organization of information》中发表了它。
 

二、AVL Tree 的特点


AVL树本质上还是一棵二叉搜索树,它的特点是:
1.本身首先是一棵二叉搜索树。
2.带有平衡条件:每个结点的左右子树的高度之差的绝对值(平衡因子)最多为1。
也就是说,AVL树,本质上是带了平衡功能的二叉查找树(二叉排序树,二叉搜索树)。

节点定义:

using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;

namespace Legalsoft.Truffer.Algorithm
{
    public class AVLTreeNode
    {
        public int Data { get; set; } = 0;
        public int Height { get; set; } = 0;
        public AVLTreeNode Left { get; set; } = null;
        public AVLTreeNode Right { get; set; } = null;

        public AVLTreeNode(int d)
        {
            Data = d;
            Height = 1;
        }
    }
}


 

三、AVL Tree 的常用操作

1、AVL Tree 旋转


AVL树的基本操作一般涉及运做同在不平衡的二叉查找树所运做的同样的算法。但是要进行预先或随后做一次或多次所谓的"AVL 旋转"。 
假设由于在二叉排序树上插入结点而失去平衡的最小子树根结点的指针为a(即a是离插入点最近,且平衡因子绝对值超过1的祖先结点),则失去平衡后进行进行的规律可归纳为下列四种情况:
单向右旋平衡处理LL:由于在*a的左子树根结点的左子树上插入结点,*a的平衡因子由1增至2,致使以*a为根的子树失去平衡,则需进行一次右旋转操作;
单向左旋平衡处理RR:由于在*a的右子树根结点的右子树上插入结点,*a的平衡因子由-1变为-2,致使以*a为根的子树失去平衡,则需进行一次左旋转操作;
双向旋转(先左后右)平衡处理LR:由于在*a的左子树根结点的右子树上插入结点,*a的平衡因子由1增至2,致使以*a为根的子树失去平衡,则需进行两次旋转(先左旋后右旋)操作。
双向旋转(先右后左)平衡处理RL:由于在*a的右子树根结点的左子树上插入结点,*a的平衡因子由-1变为-2,致使以*a为根的子树失去平衡,则需进行两次旋转(先右旋后左旋)操作。

using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;

namespace Legalsoft.Truffer.Algorithm
{
    public partial class AVLTree
    {
        public AVLTreeNode root { get; set; } = null;

        private int Height(AVLTreeNode N)
        {
            if (N == null)
            {
                return 0;
            }
            return N.Height;
        }

        public AVLTreeNode Right_Rotate(AVLTreeNode y)
        {
            AVLTreeNode x = y.Left;
            AVLTreeNode T2 = x.Right;

            x.Right = y;
            y.Left = T2;

            y.Height = Math.Max(Height(y.Left), Height(y.Right)) + 1;
            x.Height = Math.Max(Height(x.Left), Height(x.Right)) + 1;

            return x;
        }

        public AVLTreeNode Left_Rotate(AVLTreeNode x)
        {
            AVLTreeNode y = x.Right;
            AVLTreeNode T2 = y.Left;

            y.Left = x;
            x.Right = T2;

            x.Height = Math.Max(Height(x.Left), Height(x.Right)) + 1;
            y.Height = Math.Max(Height(y.Left), Height(y.Right)) + 1;

            return y;
        }

        private int Balance(AVLTreeNode N)
        {
            if (N == null)
            {
                return 0;
            }
            return Height(N.Left) - Height(N.Right);
        }
    }
}

2、AVL Tree 节点插入


向AVL树插入可以通过如同它是未平衡的二叉查找树一样把给定的值插入树中,接着自底向上向根节点折回,于在插入期间成为不平衡的所有节点上进行旋转来完成。

在平衡的的二叉排序树Balanced BST上插入一个新的数据元素e的递归算法可描述如下:

若BBST为空树,则插入一个数据元素为e的新结点作为BBST的根结点,树的深度增1;若e的关键字和BBST的根结点的关键字相等,则不进行; 若e的关键字小于BBST的根结点的关键字,而且在BBST的左子树中不存在和e有相同关键字的结点,则将e插入在BBST的左子树上,并且当插入之后的左子树深度增加(+1)时,分别就下列不同情况处理之:BBST的根结点的平衡因子为-1(右子树的深度大于左子树的深度,则将根结点的平衡因子更改为0,BBST的深度不变; BBST的根结点的平衡因子为0(左、右子树的深度相等):则将根结点的平衡因子更改为1,BBST的深度增1; BBST的根结点的平衡因子为1(左子树的深度大于右子树的深度):则若BBST的左子树根结点的平衡因子为1:则需进行单向右旋平衡处理,并且在右旋处理之后,将根结点和其右子树根结点的平衡因子更改为0,树的深度不变; 若e的关键字大于BBST的根结点的关键字,而且在BBST的右子树中不存在和e有相同关键字的结点,则将e插入在BBST的右子树上,并且当插入之后的右子树深度增加(+1)时,分别就不同情况处理之。

using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;

namespace Legalsoft.Truffer.Algorithm
{
    public partial class AVLTree
    {
        public AVLTreeNode Insert(AVLTreeNode node, int data)
        {
            if (node == null)
            {
                root = (new AVLTreeNode(data));
                return root;
            }
            if (data < node.Data)
            {
                node.Left = Insert(node.Left, data);
            }
            else if (data > node.Data)
            {
                node.Right = Insert(node.Right, data);
            }
            else
            {
                return node;
            }

            node.Height = 1 + Math.Max(Height(node.Left), Height(node.Right));

            int balance = Balance(node);

            if (balance > 1 && data < node.Left.Data)
            {
                return Right_Rotate(node);
            }
            if (balance < -1 && data > node.Right.Data)
            {
                return Left_Rotate(node);
            }
            if (balance > 1 && data > node.Left.Data)
            {
                node.Left = Left_Rotate(node.Left);
                return Right_Rotate(node);
            }

            if (balance < -1 && data < node.Right.Data)
            {
                node.Right = Right_Rotate(node.Right);
                return Left_Rotate(node);
            }

            return node;
        }
    }
}

3、AVL Tree 节点删除


从AVL树中删除可以通过把要删除的节点向下旋转成一个叶子节点,接着直接剪除这个叶子节点来完成。

代码与插入类似,请自行补充。

也可以关注本文,后续补充。

4、AVL Tree 节点遍历


AVL树的遍历同在一般BST完全一样的进行,因为AVL树总是保持平衡的。不需要特殊的准备,树的结构不会由于查询而改变。
 

using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;

namespace Legalsoft.Truffer.Algorithm
{
    public partial class AVLTree
    {
        public List OrderList { get; set; } = new List();

        public void Traversal(AVLTreeNode node)
        {
            if (node != null)
            {
                OrderList.Add(node.Data);
                Traversal(node.Left);
                Traversal(node.Right);
            }
        }

        public static List InOrder_Traversal(AVLTreeNode root)
        {
            List list = new List();
            if (root == null)
            {
                return list;
            }

            Stack s = new Stack();
            AVLTreeNode curr = root;

            while (curr != null || s.Count > 0)
            {
                while (curr != null)
                {
                    s.Push(curr);
                    curr = curr.Left;
                }

                curr = s.Pop();

                list.Add(curr.Data);

                curr = curr.Right;
            }

            return list;
        }
    }
}

你可能感兴趣的:(C#算法演义,Algorithm,Recipes,c#,开发语言,AVL,二叉树,树)