.NET源码中的SortedSet

SortedSet<T>是一个排序的无重复数据集合,其基本数据结构如下:其原理是一个红黑二叉树(平衡查找树),并将根结点做为关键数据结构。

  public class SortedSet<T> : ISet<T>, ICollection<T>, IEnumerable<T>, ICollection, IEnumerable, ISerializable, IDeserializationCallback
  {
    internal const int StackAllocThreshold = 100;
    private SortedSet<T>.Node root;
    private IComparer<T> comparer;
    private int count;

注意到这里有一个内部Node类,的定义如下:比普通树节点多一个bool型的IsRed标识此节点是否是红色节点。

 internal class Node
    {
      public bool IsRed;
      public T Item;
      public SortedSet<T>.Node Left;
      public SortedSet<T>.Node Right;

      public Node(T item)
      {
        this.Item = item;
        this.IsRed = true;
      }

      [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
      public Node(T item, bool isRed)
      {
        this.Item = item;
        this.IsRed = isRed;
      }
    }


先科普一下红黑树的基本性质:

  • 节点是红色或黑色。
  • 根是黑色。
  • 所有叶子都是黑色(叶子是NIL节点)。
  • 每个红色节点必须有两个黑色的子节点。(从每个叶子到根的所有路径上不能有两个连续的红色节点。)
  • 从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点。
如下图所示:(配图来自wikipedia)


添加新节点的实现如下:如果根节点为空,则把新节点作为根节点。过程相当复杂。

internal virtual bool AddIfNotPresent(T item)
    {
      if (this.root == null)
      {
        this.root = new SortedSet<T>.Node(item, false);
        this.count = 1;
        ++this.version;
        return true;
      }
      else
      {
        SortedSet<T>.Node node = this.root;
        SortedSet<T>.Node parent = (SortedSet<T>.Node) null;
        SortedSet<T>.Node grandParent = (SortedSet<T>.Node) null;
        SortedSet<T>.Node greatGrandParent = (SortedSet<T>.Node) null;
        ++this.version;
        int num = 0;
        for (; node != null; node = num < 0 ? node.Left : node.Right)
        {
          num = this.comparer.Compare(item, node.Item);
          if (num == 0)
          {
            this.root.IsRed = false;
            return false;
          }
          else
          {
            if (SortedSet<T>.Is4Node(node))
            {
              SortedSet<T>.Split4Node(node);
              if (SortedSet<T>.IsRed(parent))
                this.InsertionBalance(node, ref parent, grandParent, greatGrandParent);
            }
            greatGrandParent = grandParent;
            grandParent = parent;
            parent = node;
          }
        }
        SortedSet<T>.Node current = new SortedSet<T>.Node(item);
        if (num > 0)
          parent.Right = current;
        else
          parent.Left = current;
        if (parent.IsRed)
          this.InsertionBalance(current, ref parent, grandParent, greatGrandParent);
        this.root.IsRed = false;
        ++this.count;
        return true;
      }
    }

其中判断节点是否是4叉节点的实现是:

 private static bool Is4Node(SortedSet<T>.Node node)
    {
      if (SortedSet<T>.IsRed(node.Left))
        return SortedSet<T>.IsRed(node.Right);
      else
        return false;
    }

其中判断节点是否是2叉节点的实现是:

    private static bool Is2Node(SortedSet<T>.Node node)
    {
      if (SortedSet<T>.IsBlack(node) && SortedSet<T>.IsNullOrBlack(node.Left))
        return SortedSet<T>.IsNullOrBlack(node.Right);
      else
        return false;
    }

其中判断节点是黑节点的实现是:

    private static bool IsBlack(SortedSet<T>.Node node)
    {
      if (node != null)
        return !node.IsRed;
      else
        return false;
    }

而判断节点是红节点的实现是:

    private static bool IsRed(SortedSet<T>.Node node)
    {
      if (node != null)
        return node.IsRed;
      else
        return false;
    }

而分离4叉节点的实现是:

    private static void Split4Node(SortedSet<T>.Node node)
    {
      node.IsRed = true;
      node.Left.IsRed = false;
      node.Right.IsRed = false;
    }

InsertBalance的实现如下:

    private void InsertionBalance(SortedSet<T>.Node current, ref SortedSet<T>.Node parent, SortedSet<T>.Node grandParent, SortedSet<T>.Node greatGrandParent)
    {
      bool flag1 = grandParent.Right == parent;
      bool flag2 = parent.Right == current;
      SortedSet<T>.Node newChild;
      if (flag1 == flag2)
      {
        newChild = flag2 ? SortedSet<T>.RotateLeft(grandParent) : SortedSet<T>.RotateRight(grandParent);
      }
      else
      {
        newChild = flag2 ? SortedSet<T>.RotateLeftRight(grandParent) : SortedSet<T>.RotateRightLeft(grandParent);
        parent = greatGrandParent;
      }
      grandParent.IsRed = true;
      newChild.IsRed = false;
      this.ReplaceChildOfNodeOrRoot(greatGrandParent, grandParent, newChild);
    }

在这个过程中涉及到了左旋,左右旋和右旋,右左旋,它们的实现分别是:

左旋:

    private static SortedSet<T>.Node RotateLeft(SortedSet<T>.Node node)
    {
      SortedSet<T>.Node node1 = node.Right;
      node.Right = node1.Left;
      node1.Left = node;
      return node1;
    }

左右旋:

    private static SortedSet<T>.Node RotateLeftRight(SortedSet<T>.Node node)
    {
      SortedSet<T>.Node node1 = node.Left;
      SortedSet<T>.Node node2 = node1.Right;
      node.Left = node2.Right;
      node2.Right = node;
      node1.Right = node2.Left;
      node2.Left = node1;
      return node2;
    }

右旋:

    private static SortedSet<T>.Node RotateRight(SortedSet<T>.Node node)
    {
      SortedSet<T>.Node node1 = node.Left;
      node.Left = node1.Right;
      node1.Right = node;
      return node1;
    }

右左旋:

    private static SortedSet<T>.Node RotateRightLeft(SortedSet<T>.Node node)
    {
      SortedSet<T>.Node node1 = node.Right;
      SortedSet<T>.Node node2 = node1.Left;
      node.Right = node2.Left;
      node2.Left = node;
      node1.Left = node2.Right;
      node2.Right = node1;
      return node2;
    }

替换子节点的实现:

private void ReplaceChildOfNodeOrRoot(SortedSet<T>.Node parent, SortedSet<T>.Node child, SortedSet<T>.Node newChild)
    {
      if (parent != null)
      {
        if (parent.Left == child)
          parent.Left = newChild;
        else
          parent.Right = newChild;
      }
      else
        this.root = newChild;
    }


广度优先遍历红黑树的实现是:

    internal virtual bool BreadthFirstTreeWalk(TreeWalkPredicate<T> action)
    {
      if (this.root == null)
        return true;
      List<SortedSet<T>.Node> list = new List<SortedSet<T>.Node>();
      list.Add(this.root);
      while (list.Count != 0)
      {
        SortedSet<T>.Node node = list[0];
        list.RemoveAt(0);
        if (!action(node))
          return false;
        if (node.Left != null)
          list.Add(node.Left);
        if (node.Right != null)
          list.Add(node.Right);
      }
      return true;
    }

中序遍历的实现如下:

internal virtual bool InOrderTreeWalk(TreeWalkPredicate<T> action, bool reverse)
    {
      if (this.root == null)
        return true;
      Stack<SortedSet<T>.Node> stack = new Stack<SortedSet<T>.Node>(2 * SortedSet<T>.log2(this.Count + 1));
      for (SortedSet<T>.Node node = this.root; node != null; node = reverse ? node.Right : node.Left)
        stack.Push(node);
      while (stack.Count != 0)
      {
        SortedSet<T>.Node node1 = stack.Pop();
        if (!action(node1))
          return false;
        for (SortedSet<T>.Node node2 = reverse ? node1.Left : node1.Right; node2 != null; node2 = reverse ? node2.Right : node2.Left)
          stack.Push(node2);
      }
      return true;
    }


查找节点的实现如下:

internal virtual SortedSet<T>.Node FindNode(T item)
    {
      for (SortedSet<T>.Node node = this.root; node != null; {
        int num;
        node = num < 0 ? node.Left : node.Right;
      }
      )
      {
        num = this.comparer.Compare(item, node.Item);
        if (num == 0)
          return node;
      }
      return (SortedSet<T>.Node) null;
    }

删除某个节点值的实现如下:

internal virtual bool DoRemove(T item)
    {
      if (this.root == null)
        return false;
      ++this.version;
      SortedSet<T>.Node node1 = this.root;
      SortedSet<T>.Node node2 = (SortedSet<T>.Node) null;
      SortedSet<T>.Node node3 = (SortedSet<T>.Node) null;
      SortedSet<T>.Node match = (SortedSet<T>.Node) null;
      SortedSet<T>.Node parentOfMatch = (SortedSet<T>.Node) null;
      bool flag = false;
      for (; node1 != null; {
        int num;
        node1 = num >= 0 ? node1.Right : node1.Left;
      }
      )
      {
        if (SortedSet<T>.Is2Node(node1))
        {
          if (node2 == null)
          {
            node1.IsRed = true;
          }
          else
          {
            SortedSet<T>.Node node4 = SortedSet<T>.GetSibling(node1, node2);
            if (node4.IsRed)
            {
              if (node2.Right == node4)
                SortedSet<T>.RotateLeft(node2);
              else
                SortedSet<T>.RotateRight(node2);
              node2.IsRed = true;
              node4.IsRed = false;
              this.ReplaceChildOfNodeOrRoot(node3, node2, node4);
              node3 = node4;
              if (node2 == match)
                parentOfMatch = node4;
              node4 = node2.Left == node1 ? node2.Right : node2.Left;
            }
            if (SortedSet<T>.Is2Node(node4))
            {
              SortedSet<T>.Merge2Nodes(node2, node1, node4);
            }
            else
            {
              TreeRotation treeRotation = SortedSet<T>.RotationNeeded(node2, node1, node4);
              SortedSet<T>.Node newChild = (SortedSet<T>.Node) null;
              switch (treeRotation)
              {
                case TreeRotation.LeftRotation:
                  node4.Right.IsRed = false;
                  newChild = SortedSet<T>.RotateLeft(node2);
                  break;
                case TreeRotation.RightRotation:
                  node4.Left.IsRed = false;
                  newChild = SortedSet<T>.RotateRight(node2);
                  break;
                case TreeRotation.RightLeftRotation:
                  newChild = SortedSet<T>.RotateRightLeft(node2);
                  break;
                case TreeRotation.LeftRightRotation:
                  newChild = SortedSet<T>.RotateLeftRight(node2);
                  break;
              }
              newChild.IsRed = node2.IsRed;
              node2.IsRed = false;
              node1.IsRed = true;
              this.ReplaceChildOfNodeOrRoot(node3, node2, newChild);
              if (node2 == match)
                parentOfMatch = newChild;
            }
          }
        }
        num = flag ? -1 : this.comparer.Compare(item, node1.Item);
        if (num == 0)
        {
          flag = true;
          match = node1;
          parentOfMatch = node2;
        }
        node3 = node2;
        node2 = node1;
      }
      if (match != null)
      {
        this.ReplaceNode(match, parentOfMatch, node2, node3);
        --this.count;
      }
      if (this.root != null)
        this.root.IsRed = false;
      return flag;
    }

其中得到兄妹节点的实现如下:

  private static SortedSet<T>.Node GetSibling(SortedSet<T>.Node node, SortedSet<T>.Node parent)
    {
      if (parent.Left == node)
        return parent.Right;
      else
        return parent.Left;
    }

其中合并两个节点的实现如下:

    private static void Merge2Nodes(SortedSet<T>.Node parent, SortedSet<T>.Node child1, SortedSet<T>.Node child2)
    {
      parent.IsRed = false;
      child1.IsRed = true;
      child2.IsRed = true;
    }

RotationNeeded的实现如下:


    private static TreeRotation RotationNeeded(SortedSet<T>.Node parent, SortedSet<T>.Node current, SortedSet<T>.Node sibling)
    {
      if (SortedSet<T>.IsRed(sibling.Left))
        return parent.Left == current ? TreeRotation.RightLeftRotation : TreeRotation.RightRotation;
      else
        return parent.Left == current ? TreeRotation.LeftRotation : TreeRotation.LeftRightRotation;
    }

替换节点的实现如下:

 private void ReplaceNode(SortedSet<T>.Node match, SortedSet<T>.Node parentOfMatch, SortedSet<T>.Node succesor, SortedSet<T>.Node parentOfSuccesor)
    {
      if (succesor == match)
      {
        succesor = match.Left;
      }
      else
      {
        if (succesor.Right != null)
          succesor.Right.IsRed = false;
        if (parentOfSuccesor != match)
        {
          parentOfSuccesor.Left = succesor.Right;
          succesor.Right = match.Right;
        }
        succesor.Left = match.Left;
      }
      if (succesor != null)
        succesor.IsRed = match.IsRed;
      this.ReplaceChildOfNodeOrRoot(parentOfMatch, match, succesor);
    }

实现的代码量有点大。慢慢看。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值