zoukankan      html  css  js  c++  java
  • 6天通吃树结构—— 第二天 平衡二叉树

           

          上一篇我们聊过,二叉查找树不是严格的O(logN),导致了在真实场景中没有用武之地,谁也不愿意有O(N)的情况发生,

    作为一名码农,肯定会希望能把“范围查找”做到地球人都不能优化的地步。

         当有很多数据灌到我的树中时,我肯定会希望最好是以“完全二叉树”的形式展现,这样我才能做到“查找”是严格的O(logN),

    比如把这种”树“调正到如下结构。

         

    这里就涉及到了“树节点”的旋转,也是我们今天要聊到的内容。

    一:平衡二叉树(AVL)

    1:定义

           父节点的左子树和右子树的高度之差不能大于1,也就是说不能高过1层,否则该树就失衡了,此时就要旋转节点,在

    编码时,我们可以记录当前节点的高度,比如空节点是-1,叶子节点是0,非叶子节点的height往根节点递增,比如在下图

    中我们认为树的高度为h=2。

     1 #region 平衡二叉树节点
     2     /// <summary>
     3     /// 平衡二叉树节点
     4     /// </summary>
     5     /// <typeparam name="K"></typeparam>
     6     /// <typeparam name="V"></typeparam>
     7     public class AVLNode<K, V>
     8     {
     9         /// <summary>
    10         /// 节点元素
    11         /// </summary>
    12         public K key;
    13 
    14         /// <summary>
    15         /// 增加一个高度信息
    16         /// </summary>
    17         public int height;
    18 
    19         /// <summary>
    20         /// 节点中的附加值
    21         /// </summary>
    22         public HashSet<V> attach = new HashSet<V>();
    23 
    24         /// <summary>
    25         /// 左节点
    26         /// </summary>
    27         public AVLNode<K, V> left;
    28 
    29         /// <summary>
    30         /// 右节点
    31         /// </summary>
    32         public AVLNode<K, V> right;
    33 
    34         public AVLNode() { }
    35 
    36         public AVLNode(K key, V value, AVLNode<K, V> left, AVLNode<K, V> right)
    37         {
    38             //KV键值对
    39             this.key = key;
    40             this.attach.Add(value);
    41 
    42             this.left = left;
    43             this.right = right;
    44         }
    45     }
    46     #endregion

    2:旋转

        节点再怎么失衡都逃不过4种情况,下面我们一一来看一下。

    ① 左左情况(左子树的左边节点)

    我们看到,在向树中追加“节点1”的时候,根据定义我们知道这样会导致了“节点3"失衡,满足“左左情况“,可以这样想,把这

    棵树比作齿轮,我们在“节点5”处把齿轮往下拉一个位置,也就变成了后面这样“平衡”的形式,如果用动画解释就最好理解了。

     1         #region 第一种:左左旋转(单旋转)
     2         /// <summary>
     3         /// 第一种:左左旋转(单旋转)
     4         /// </summary>
     5         /// <param name="node"></param>
     6         /// <returns></returns>
     7         public AVLNode<K, V> RotateLL(AVLNode<K, V> node)
     8         {
     9             //top:需要作为顶级节点的元素
    10             var top = node.left;
    11 
    12             //先截断当前节点的左孩子
    13             node.left = top.right;
    14 
    15             //将当前节点作为temp的右孩子
    16             top.right = node;
    17 
    18             //计算当前两个节点的高度
    19             node.height = Math.Max(Height(node.left), Height(node.right)) + 1;
    20             top.height = Math.Max(Height(top.left), Height(top.right)) + 1;
    21 
    22             return top;
    23         }
    24         #endregion

    ② 右右情况(右子树的右边节点)

    同样,”节点5“满足”右右情况“,其实我们也看到,这两种情况是一种镜像,当然操作方式也大同小异,我们在”节点1“的地方

    将树往下拉一位,最后也就形成了我们希望的平衡效果。

     1         #region 第二种:右右旋转(单旋转)
     2         /// <summary>
     3         /// 第二种:右右旋转(单旋转)
     4         /// </summary>
     5         /// <param name="node"></param>
     6         /// <returns></returns>
     7         public AVLNode<K, V> RotateRR(AVLNode<K, V> node)
     8         {
     9             //top:需要作为顶级节点的元素
    10             var top = node.right;
    11 
    12             //先截断当前节点的右孩子
    13             node.right = top.left;
    14 
    15             //将当前节点作为temp的右孩子
    16             top.left = node;
    17 
    18             //计算当前两个节点的高度
    19             node.height = Math.Max(Height(node.left), Height(node.right)) + 1;
    20             top.height = Math.Max(Height(top.left), Height(top.right)) + 1;
    21 
    22             return top;
    23         }
    24         #endregion

    ③左右情况(左子树的右边节点)

    从图中我们可以看到,当我们插入”节点3“时,“节点5”处失衡,注意,找到”失衡点“是非常重要的,当面对”左右情况“时,我们将

    失衡点的左子树进行"右右情况旋转",然后进行”左左情况旋转“,经过这样两次的旋转就OK了,很有意思,对吧。

     1         #region 第三种:左右旋转(双旋转)
     2         /// <summary>
     3         /// 第三种:左右旋转(双旋转)
     4         /// </summary>
     5         /// <param name="node"></param>
     6         /// <returns></returns>
     7         public AVLNode<K, V> RotateLR(AVLNode<K, V> node)
     8         {
     9             //先进行RR旋转
    10             node.left = RotateRR(node.left);
    11 
    12             //再进行LL旋转
    13             return RotateLL(node);
    14         }
    15         #endregion

    ④右左情况(右子树的左边节点)

    这种情况和“情景3”也是一种镜像关系,很简单,我们找到了”节点15“是失衡点,然后我们将”节点15“的右子树进行”左左情况旋转“,

    然后进行”右右情况旋转“,最终得到了我们满意的平衡。

     1         #region 第四种:右左旋转(双旋转)
     2         /// <summary>
     3         /// 第四种:右左旋转(双旋转)
     4         /// </summary>
     5         /// <param name="node"></param>
     6         /// <returns></returns>
     7         public AVLNode<K, V> RotateRL(AVLNode<K, V> node)
     8         {
     9             //执行左左旋转
    10             node.right = RotateLL(node.right);
    11 
    12             //再执行右右旋转
    13             return RotateRR(node);
    14 
    15         }
    16         #endregion

    3:添加

        如果我们理解了上面的这几种旋转,那么添加方法简直是轻而易举,出现了哪一种情况调用哪一种方法而已。

     1  #region 添加操作
     2         /// <summary>
     3         /// 添加操作
     4         /// </summary>
     5         /// <param name="key"></param>
     6         /// <param name="value"></param>
     7         /// <param name="tree"></param>
     8         /// <returns></returns>
     9         public AVLNode<K, V> Add(K key, V value, AVLNode<K, V> tree)
    10         {
    11             if (tree == null)
    12                 tree = new AVLNode<K, V>(key, value, null, null);
    13 
    14             //左子树
    15             if (key.CompareTo(tree.key) < 0)
    16             {
    17                 tree.left = Add(key, value, tree.left);
    18 
    19                 //如果说相差等于2就说明这棵树需要旋转了
    20                 if (Height(tree.left) - Height(tree.right) == 2)
    21                 {
    22                     //说明此时是左左旋转
    23                     if (key.CompareTo(tree.left.key) < 0)
    24                     {
    25                         tree = RotateLL(tree);
    26                     }
    27                     else
    28                     {
    29                         //属于左右旋转
    30                         tree = RotateLR(tree);
    31                     }
    32                 }
    33             }
    34 
    35             //右子树
    36             if (key.CompareTo(tree.key) > 0)
    37             {
    38                 tree.right = Add(key, value, tree.right);
    39 
    40                 if ((Height(tree.right) - Height(tree.left) == 2))
    41                 {
    42                     //此时是右右旋转
    43                     if (key.CompareTo(tree.right.key) > 0)
    44                     {
    45                         tree = RotateRR(tree);
    46                     }
    47                     else
    48                     {
    49                         //属于右左旋转
    50                         tree = RotateRL(tree);
    51                     }
    52                 }
    53             }
    54 
    55             //将value追加到附加值中(也可对应重复元素)
    56             if (key.CompareTo(tree.key) == 0)
    57                 tree.attach.Add(value);
    58 
    59             //计算高度
    60             tree.height = Math.Max(Height(tree.left), Height(tree.right)) + 1;
    61 
    62             return tree;
    63         }
    64         #endregion

    4:删除

    删除方法跟添加方法也类似,当删除一个结点的时候,可能会引起祖先结点的失衡,所以在每次”结点“回退的时候计算结点高度。

     1 #region 删除当前树中的节点
     2         /// <summary>
     3         /// 删除当前树中的节点
     4         /// </summary>
     5         /// <param name="key"></param>
     6         /// <param name="tree"></param>
     7         /// <returns></returns>
     8         public AVLNode<K, V> Remove(K key, V value, AVLNode<K, V> tree)
     9         {
    10             if (tree == null)
    11                 return null;
    12 
    13             //左子树
    14             if (key.CompareTo(tree.key) < 0)
    15             {
    16                 tree.left = Remove(key, value, tree.left);
    17 
    18                 //如果说相差等于2就说明这棵树需要旋转了
    19                 if (Height(tree.left) - Height(tree.right) == 2)
    20                 {
    21                     //说明此时是左左旋转
    22                     if (key.CompareTo(tree.left.key) < 0)
    23                     {
    24                         tree = RotateLL(tree);
    25                     }
    26                     else
    27                     {
    28                         //属于左右旋转
    29                         tree = RotateLR(tree);
    30                     }
    31                 }
    32             }
    33             //右子树
    34             if (key.CompareTo(tree.key) > 0)
    35             {
    36                 tree.right = Remove(key, value, tree.right);
    37 
    38                 if ((Height(tree.right) - Height(tree.left) == 2))
    39                 {
    40                     //此时是右右旋转
    41                     if (key.CompareTo(tree.right.key) > 0)
    42                     {
    43                         tree = RotateRR(tree);
    44                     }
    45                     else
    46                     {
    47                         //属于右左旋转
    48                         tree = RotateRL(tree);
    49                     }
    50                 }
    51             }
    52             /*相等的情况*/
    53             if (key.CompareTo(tree.key) == 0)
    54             {
    55                 //判断里面的HashSet是否有多值
    56                 if (tree.attach.Count > 1)
    57                 {
    58                     //实现惰性删除
    59                     tree.attach.Remove(value);
    60                 }
    61                 else
    62                 {
    63                     //有两个孩子的情况
    64                     if (tree.left != null && tree.right != null)
    65                     {
    66                         //根据平衡二叉树的中顺遍历,需要找到”有子树“的最小节点
    67                         tree.key = FindMin(tree.right).key;
    68 
    69                         //删除右子树的指定元素
    70                         tree.right = Remove(tree.key, value, tree.right);
    71                     }
    72                     else
    73                     {
    74                         //自减高度
    75                         tree = tree.left == null ? tree.right : tree.left;
    76 
    77                         //如果删除的是叶子节点直接返回
    78                         if (tree == null)
    79                             return null;
    80                     }
    81                 }
    82             }
    83 
    84             //统计高度
    85             tree.height = Math.Max(Height(tree.left), Height(tree.right)) + 1;
    86 
    87             return tree;
    88         }
    89         #endregion

    5: 测试

    不像上一篇不能在二叉树中灌有序数据,平衡二叉树就没关系了,我们的需求是检索2012-7-30 4:00:00 到 2012-7-30 5:00:00

    的登陆用户的ID,数据量在500w,看看平衡二叉树是如何秒杀对手。

    View Code
      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 using System.Text;
      5 using System.Threading;
      6 using System.IO;
      7 using System.Diagnostics;
      8 
      9 namespace DataStruct
     10 {
     11     class Program
     12     {
     13         static void Main(string[] args)
     14         {
     15             AVLTree<int, int> avl = new AVLTree<int, int>();
     16 
     17             Dictionary<DateTime, int> dic = new Dictionary<DateTime, int>();
     18 
     19             AVLTree<DateTime, int> tree = new AVLTree<DateTime, int>();
     20 
     21             //500w
     22             for (int i = 1; i < 5000000; i++)
     23             {
     24                 dic.Add(DateTime.Now.AddMinutes(i), i);
     25 
     26                 tree.Add(DateTime.Now.AddMinutes(i), i);
     27             }
     28 
     29             //检索2012-7-30 4:00:00 到 2012-7-30 5:00:00的登陆人数
     30             var min = Convert.ToDateTime("2012/7/30 4:00:00");
     31 
     32             var max = Convert.ToDateTime("2012/7/30 5:00:00");
     33 
     34             var watch = Stopwatch.StartNew();
     35 
     36             var result1 = dic.Keys.Where(i => i >= min && i <= max).Select(i => dic[i]).ToList();
     37 
     38             watch.Stop();
     39 
     40             Console.WriteLine("字典查找耗费时间:{0}ms", watch.ElapsedMilliseconds);
     41 
     42             watch = Stopwatch.StartNew();
     43 
     44             var result2 = tree.SearchRange(min, max);
     45 
     46             watch.Stop();
     47 
     48             Console.WriteLine("平衡二叉树查找耗费时间:{0}ms", watch.ElapsedMilliseconds);
     49         }
     50     }
     51 
     52     #region 平衡二叉树节点
     53     /// <summary>
     54     /// 平衡二叉树节点
     55     /// </summary>
     56     /// <typeparam name="K"></typeparam>
     57     /// <typeparam name="V"></typeparam>
     58     public class AVLNode<K, V>
     59     {
     60         /// <summary>
     61         /// 节点元素
     62         /// </summary>
     63         public K key;
     64 
     65         /// <summary>
     66         /// 增加一个高度信息
     67         /// </summary>
     68         public int height;
     69 
     70         /// <summary>
     71         /// 节点中的附加值
     72         /// </summary>
     73         public HashSet<V> attach = new HashSet<V>();
     74 
     75         /// <summary>
     76         /// 左节点
     77         /// </summary>
     78         public AVLNode<K, V> left;
     79 
     80         /// <summary>
     81         /// 右节点
     82         /// </summary>
     83         public AVLNode<K, V> right;
     84 
     85         public AVLNode() { }
     86 
     87         public AVLNode(K key, V value, AVLNode<K, V> left, AVLNode<K, V> right)
     88         {
     89             //KV键值对
     90             this.key = key;
     91             this.attach.Add(value);
     92 
     93             this.left = left;
     94             this.right = right;
     95         }
     96     }
     97     #endregion
     98 
     99     public class AVLTree<K, V> where K : IComparable
    100     {
    101         public AVLNode<K, V> node = null;
    102 
    103         #region 添加操作
    104         /// <summary>
    105         /// 添加操作
    106         /// </summary>
    107         /// <param name="key"></param>
    108         /// <param name="value"></param>
    109         public void Add(K key, V value)
    110         {
    111             node = Add(key, value, node);
    112         }
    113         #endregion
    114 
    115         #region 添加操作
    116         /// <summary>
    117         /// 添加操作
    118         /// </summary>
    119         /// <param name="key"></param>
    120         /// <param name="value"></param>
    121         /// <param name="tree"></param>
    122         /// <returns></returns>
    123         public AVLNode<K, V> Add(K key, V value, AVLNode<K, V> tree)
    124         {
    125             if (tree == null)
    126                 tree = new AVLNode<K, V>(key, value, null, null);
    127 
    128             //左子树
    129             if (key.CompareTo(tree.key) < 0)
    130             {
    131                 tree.left = Add(key, value, tree.left);
    132 
    133                 //如果说相差等于2就说明这棵树需要旋转了
    134                 if (Height(tree.left) - Height(tree.right) == 2)
    135                 {
    136                     //说明此时是左左旋转
    137                     if (key.CompareTo(tree.left.key) < 0)
    138                     {
    139                         tree = RotateLL(tree);
    140                     }
    141                     else
    142                     {
    143                         //属于左右旋转
    144                         tree = RotateLR(tree);
    145                     }
    146                 }
    147             }
    148 
    149             //右子树
    150             if (key.CompareTo(tree.key) > 0)
    151             {
    152                 tree.right = Add(key, value, tree.right);
    153 
    154                 if ((Height(tree.right) - Height(tree.left) == 2))
    155                 {
    156                     //此时是右右旋转
    157                     if (key.CompareTo(tree.right.key) > 0)
    158                     {
    159                         tree = RotateRR(tree);
    160                     }
    161                     else
    162                     {
    163                         //属于右左旋转
    164                         tree = RotateRL(tree);
    165                     }
    166                 }
    167             }
    168 
    169             //将value追加到附加值中(也可对应重复元素)
    170             if (key.CompareTo(tree.key) == 0)
    171                 tree.attach.Add(value);
    172 
    173             //计算高度
    174             tree.height = Math.Max(Height(tree.left), Height(tree.right)) + 1;
    175 
    176             return tree;
    177         }
    178         #endregion
    179 
    180         #region 计算当前节点的高度
    181         /// <summary>
    182         /// 计算当前节点的高度
    183         /// </summary>
    184         /// <param name="node"></param>
    185         /// <returns></returns>
    186         public int Height(AVLNode<K, V> node)
    187         {
    188             return node == null ? -1 : node.height;
    189         }
    190         #endregion
    191 
    192         #region 第一种:左左旋转(单旋转)
    193         /// <summary>
    194         /// 第一种:左左旋转(单旋转)
    195         /// </summary>
    196         /// <param name="node"></param>
    197         /// <returns></returns>
    198         public AVLNode<K, V> RotateLL(AVLNode<K, V> node)
    199         {
    200             //top:需要作为顶级节点的元素
    201             var top = node.left;
    202 
    203             //先截断当前节点的左孩子
    204             node.left = top.right;
    205 
    206             //将当前节点作为temp的右孩子
    207             top.right = node;
    208 
    209             //计算当前两个节点的高度
    210             node.height = Math.Max(Height(node.left), Height(node.right)) + 1;
    211             top.height = Math.Max(Height(top.left), Height(top.right)) + 1;
    212 
    213             return top;
    214         }
    215         #endregion
    216 
    217         #region 第二种:右右旋转(单旋转)
    218         /// <summary>
    219         /// 第二种:右右旋转(单旋转)
    220         /// </summary>
    221         /// <param name="node"></param>
    222         /// <returns></returns>
    223         public AVLNode<K, V> RotateRR(AVLNode<K, V> node)
    224         {
    225             //top:需要作为顶级节点的元素
    226             var top = node.right;
    227 
    228             //先截断当前节点的右孩子
    229             node.right = top.left;
    230 
    231             //将当前节点作为temp的右孩子
    232             top.left = node;
    233 
    234             //计算当前两个节点的高度
    235             node.height = Math.Max(Height(node.left), Height(node.right)) + 1;
    236             top.height = Math.Max(Height(top.left), Height(top.right)) + 1;
    237 
    238             return top;
    239         }
    240         #endregion
    241 
    242         #region 第三种:左右旋转(双旋转)
    243         /// <summary>
    244         /// 第三种:左右旋转(双旋转)
    245         /// </summary>
    246         /// <param name="node"></param>
    247         /// <returns></returns>
    248         public AVLNode<K, V> RotateLR(AVLNode<K, V> node)
    249         {
    250             //先进行RR旋转
    251             node.left = RotateRR(node.left);
    252 
    253             //再进行LL旋转
    254             return RotateLL(node);
    255         }
    256         #endregion
    257 
    258         #region 第四种:右左旋转(双旋转)
    259         /// <summary>
    260         /// 第四种:右左旋转(双旋转)
    261         /// </summary>
    262         /// <param name="node"></param>
    263         /// <returns></returns>
    264         public AVLNode<K, V> RotateRL(AVLNode<K, V> node)
    265         {
    266             //执行左左旋转
    267             node.right = RotateLL(node.right);
    268 
    269             //再执行右右旋转
    270             return RotateRR(node);
    271 
    272         }
    273         #endregion
    274 
    275         #region 是否包含指定元素
    276         /// <summary>
    277         /// 是否包含指定元素
    278         /// </summary>
    279         /// <param name="key"></param>
    280         /// <returns></returns>
    281         public bool Contain(K key)
    282         {
    283             return Contain(key, node);
    284         }
    285         #endregion
    286 
    287         #region 是否包含指定元素
    288         /// <summary>
    289         /// 是否包含指定元素
    290         /// </summary>
    291         /// <param name="key"></param>
    292         /// <param name="tree"></param>
    293         /// <returns></returns>
    294         public bool Contain(K key, AVLNode<K, V> tree)
    295         {
    296             if (tree == null)
    297                 return false;
    298             //左子树
    299             if (key.CompareTo(tree.key) < 0)
    300                 return Contain(key, tree.left);
    301 
    302             //右子树
    303             if (key.CompareTo(tree.key) > 0)
    304                 return Contain(key, tree.right);
    305 
    306             return true;
    307         }
    308         #endregion
    309 
    310         #region 树的指定范围查找
    311         /// <summary>
    312         /// 树的指定范围查找
    313         /// </summary>
    314         /// <param name="min"></param>
    315         /// <param name="max"></param>
    316         /// <returns></returns>
    317         public HashSet<V> SearchRange(K min, K max)
    318         {
    319             HashSet<V> hashSet = new HashSet<V>();
    320 
    321             hashSet = SearchRange(min, max, hashSet, node);
    322 
    323             return hashSet;
    324         }
    325         #endregion
    326 
    327         #region 树的指定范围查找
    328         /// <summary>
    329         /// 树的指定范围查找
    330         /// </summary>
    331         /// <param name="range1"></param>
    332         /// <param name="range2"></param>
    333         /// <param name="tree"></param>
    334         /// <returns></returns>
    335         public HashSet<V> SearchRange(K min, K max, HashSet<V> hashSet, AVLNode<K, V> tree)
    336         {
    337             if (tree == null)
    338                 return hashSet;
    339 
    340             //遍历左子树(寻找下界)
    341             if (min.CompareTo(tree.key) < 0)
    342                 SearchRange(min, max, hashSet, tree.left);
    343 
    344             //当前节点是否在选定范围内
    345             if (min.CompareTo(tree.key) <= 0 && max.CompareTo(tree.key) >= 0)
    346             {
    347                 //等于这种情况
    348                 foreach (var item in tree.attach)
    349                     hashSet.Add(item);
    350             }
    351 
    352             //遍历右子树(两种情况:①:找min的下限 ②:必须在Max范围之内)
    353             if (min.CompareTo(tree.key) > 0 || max.CompareTo(tree.key) > 0)
    354                 SearchRange(min, max, hashSet, tree.right);
    355 
    356             return hashSet;
    357         }
    358         #endregion
    359 
    360         #region 找到当前树的最小节点
    361         /// <summary>
    362         /// 找到当前树的最小节点
    363         /// </summary>
    364         /// <returns></returns>
    365         public AVLNode<K, V> FindMin()
    366         {
    367             return FindMin(node);
    368         }
    369         #endregion
    370 
    371         #region 找到当前树的最小节点
    372         /// <summary>
    373         /// 找到当前树的最小节点
    374         /// </summary>
    375         /// <param name="tree"></param>
    376         /// <returns></returns>
    377         public AVLNode<K, V> FindMin(AVLNode<K, V> tree)
    378         {
    379             if (tree == null)
    380                 return null;
    381 
    382             if (tree.left == null)
    383                 return tree;
    384 
    385             return FindMin(tree.left);
    386         }
    387         #endregion
    388 
    389         #region 找到当前树的最大节点
    390         /// <summary>
    391         /// 找到当前树的最大节点
    392         /// </summary>
    393         /// <returns></returns>
    394         public AVLNode<K, V> FindMax()
    395         {
    396             return FindMin(node);
    397         }
    398         #endregion
    399 
    400         #region 找到当前树的最大节点
    401         /// <summary>
    402         /// 找到当前树的最大节点
    403         /// </summary>
    404         /// <param name="tree"></param>
    405         /// <returns></returns>
    406         public AVLNode<K, V> FindMax(AVLNode<K, V> tree)
    407         {
    408             if (tree == null)
    409                 return null;
    410 
    411             if (tree.right == null)
    412                 return tree;
    413 
    414             return FindMax(tree.right);
    415         }
    416         #endregion
    417 
    418         #region 删除当前树中的节点
    419         /// <summary>
    420         /// 删除当前树中的节点
    421         /// </summary>
    422         /// <param name="key"></param>
    423         /// <returns></returns>
    424         public void Remove(K key, V value)
    425         {
    426             node = Remove(key, value, node);
    427         }
    428         #endregion
    429 
    430         #region 删除当前树中的节点
    431         /// <summary>
    432         /// 删除当前树中的节点
    433         /// </summary>
    434         /// <param name="key"></param>
    435         /// <param name="tree"></param>
    436         /// <returns></returns>
    437         public AVLNode<K, V> Remove(K key, V value, AVLNode<K, V> tree)
    438         {
    439             if (tree == null)
    440                 return null;
    441 
    442             //左子树
    443             if (key.CompareTo(tree.key) < 0)
    444             {
    445                 tree.left = Remove(key, value, tree.left);
    446 
    447                 //如果说相差等于2就说明这棵树需要旋转了
    448                 if (Height(tree.left) - Height(tree.right) == 2)
    449                 {
    450                     //说明此时是左左旋转
    451                     if (key.CompareTo(tree.left.key) < 0)
    452                     {
    453                         tree = RotateLL(tree);
    454                     }
    455                     else
    456                     {
    457                         //属于左右旋转
    458                         tree = RotateLR(tree);
    459                     }
    460                 }
    461             }
    462             //右子树
    463             if (key.CompareTo(tree.key) > 0)
    464             {
    465                 tree.right = Remove(key, value, tree.right);
    466 
    467                 if ((Height(tree.right) - Height(tree.left) == 2))
    468                 {
    469                     //此时是右右旋转
    470                     if (key.CompareTo(tree.right.key) > 0)
    471                     {
    472                         tree = RotateRR(tree);
    473                     }
    474                     else
    475                     {
    476                         //属于右左旋转
    477                         tree = RotateRL(tree);
    478                     }
    479                 }
    480             }
    481             /*相等的情况*/
    482             if (key.CompareTo(tree.key) == 0)
    483             {
    484                 //判断里面的HashSet是否有多值
    485                 if (tree.attach.Count > 1)
    486                 {
    487                     //实现惰性删除
    488                     tree.attach.Remove(value);
    489                 }
    490                 else
    491                 {
    492                     //有两个孩子的情况
    493                     if (tree.left != null && tree.right != null)
    494                     {
    495                         //根据平衡二叉树的中顺遍历,需要找到”有子树“的最小节点
    496                         tree.key = FindMin(tree.right).key;
    497 
    498                         //删除右子树的指定元素
    499                         tree.right = Remove(tree.key, value, tree.right);
    500                     }
    501                     else
    502                     {
    503                         //自减高度
    504                         tree = tree.left == null ? tree.right : tree.left;
    505 
    506                         //如果删除的是叶子节点直接返回
    507                         if (tree == null)
    508                             return null;
    509                     }
    510                 }
    511             }
    512 
    513             //统计高度
    514             tree.height = Math.Max(Height(tree.left), Height(tree.right)) + 1;
    515 
    516             return tree;
    517         }
    518         #endregion
    519     }
    520 }

    wow,相差98倍,这个可不是一个级别啊...AVL神器。

  • 相关阅读:
    Visual Studio 2015 开发 ASP.NET 5
    全新的membership框架Asp.net Identity
    VS2013下实现移动端的跨平台开发
    用SQL语句,删除掉重复项只保留一条
    SOA IN Real World
    Asp.net负载均衡之Session
    C#时常需要调用C++DLL
    C# 支付宝接口
    好代码是怎么炼成的
    ASP.net 服务器监控
  • 原文地址:https://www.cnblogs.com/huangxincheng/p/2603956.html
Copyright © 2011-2022 走看看