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);
}
实现的代码量有点大。慢慢看。