看了一下算法导论,纸上得来终觉浅,绝知此事要躬行,所以把感兴趣的算法就写了下。
红黑树在插入,删除,查找过程中都可以保持较高的运行效率,sharpdevelop 中自定义的代码编辑控件中的document模型就是运用了红黑树。
RedBlackTree.cs
using System;
namespace Cn.Linc.Algorithms.BasicStructure
{
public enum NodeColor
{
Black,
Red
}
///
/// A binary search tree is a red-black tree if it satisfies the following red-black properties:
/// 1) Every node is either red or black.
/// 2) The root is black.
/// 3) Every leaf (NIL) is black.
/// 4) If a node is red, then both its children are black.
/// 5) For each node, all paths from the node to descendant leaves contain the same number of black nodes.
///
/// Red-black trees are one of many search-tree schemes that are "balanced" in order to
/// guarantee that basic dynamic-set operations take O(lg n) time in the worst case.
///
/// Notice, a null leaf node or parent node is colored black.
///
/// More details please find in chapter 13, Introduction to Algorithms, Second Edition
/// by Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest and Clifford Stein ISBN:0262032937
/// The MIT Press © 2001 (1180 pages)
///
/// RedBlackTreeNode type
/// IComparable type
public class RedBlackTree<T,S>
where T: RedBlackTreeNode<S>
where S: IComparable
{
private RedBlackTreeNode<S> root;
///
/// Insert a new node, at first initialize the new node as red to keep the black height
/// rule of red black tree. Insert the new node to proper position accordding to its value,
/// the fix the tree according to the defination of red black tree.
///
///
public void InsertNode(S nodeValue)
{
RedBlackTreeNode<S> newNode &#61; new RedBlackTreeNode<S>(nodeValue);
if (root &#61;&#61; null)
{
root &#61; newNode;
}
else
{
RedBlackTreeNode<S> tempX &#61; root;
RedBlackTreeNode<S> tempY &#61; null;
while (tempX !&#61; null)
{
tempY &#61; tempX;
tempX &#61; nodeValue.CompareTo(tempX.Value) > 0 ? tempX.RightChild : tempX.LeftChild;
}
if (nodeValue.CompareTo(tempY.Value) >&#61; 0)
{
tempY.RightChild &#61; newNode;
}
else
{
tempY.LeftChild &#61; newNode;
}
}
InsertFixup(newNode);
}
///
/// Delete node.
/// If the node only have one or no child, just delete it.
/// If the node has both left and right children, find its successor, delete it and copy its
/// value to the node to be deleted.
/// After deleting, fix up the tree according to defination.
///
///
public void DeleteNode(T node)
{
if (node &#61;&#61; null)
return;
if ((node &#61;&#61; root) && (root.RightChild &#61;&#61; null) && (root.LeftChild &#61;&#61; null))
{
root &#61; null;
return;
}
RedBlackTreeNode<S> tempX &#61; null, tempY &#61; null;
if (node.LeftChild &#61;&#61; null || node.RightChild &#61;&#61; null)
{
tempY &#61; node;
}
else
{
tempY &#61; GetSuccessor(node);
}
tempX &#61; (tempY.LeftChild !&#61; null) ? tempY.LeftChild : tempY.RightChild;
if (tempY.ParentNode &#61;&#61; null)
root &#61; tempX;
else
{
if (tempY &#61;&#61; tempY.ParentNode.LeftChild)
{
tempY.ParentNode.LeftChild &#61; tempX;
}
else
{
tempY.ParentNode.RightChild &#61; tempX;
}
}
if (tempY !&#61; node)
{
node.Value &#61; tempY.Value;
}
// if black node is deleted the black height rule must be violated, fix it.
if (tempY.Color &#61;&#61; NodeColor.Black)
DeleteFixup(tempX,tempY.ParentNode);
}
///
/// Find the node with specified value.
///
/// specified value
///
public RedBlackTreeNode<S> FindNode(S value)
{
RedBlackTreeNode<S> temp &#61; root;
if (root &#61;&#61; null)
{
return null;
}
do
{
if(value.CompareTo(temp.Value)&#61;&#61;0)
{
return temp;
}
else if (temp.LeftChild !&#61; null && value.CompareTo(temp.Value) < 0)
{
temp &#61; temp.LeftChild;
}
else if (temp.RightChild !&#61; null && value.CompareTo(temp.Value) > 0)
{
temp &#61; temp.RightChild;
}
else
{
return null;
}
} while (true);
}
///
/// Find the successer of specific node,
/// if the right child is not empty, the successor is the far left node of the subtree.
/// If it has a successor and its right child is null, the successor must be the nearest
/// ancestor, and the left child of the successor is ancestor of the specific node.
///
/// the specific node
///
private RedBlackTreeNode<S> GetSuccessor(RedBlackTreeNode<S> currentNode)
{
RedBlackTreeNode<S> temp &#61; null;
if (currentNode.RightChild !&#61; null)
{
temp &#61; currentNode.RightChild;
while (temp.LeftChild !&#61; null)
{
temp &#61; temp.LeftChild;
}
return temp;
}
else
{
while (temp.ParentNode !&#61; null)
{
if (temp &#61;&#61; temp.ParentNode.LeftChild)
{
return temp.ParentNode;
}
else
{
temp &#61; temp.ParentNode;
}
}
return null;
}
}
///
/// Fix up red black tree after inserting node. Three cases:
/// 1) the uncle of the node is red;
/// 2) the uncle of the node is black and the node is right child(left rotate to case 3);
/// 3) the uncle of the node is black and the node is left child;
///
///
private void InsertFixup(RedBlackTreeNode<S> node)
{
RedBlackTreeNode<S> temp &#61; null;
while (node !&#61; root && node.ParentNode.Color &#61;&#61; NodeColor.Red)
{
if (node.ParentNode &#61;&#61; node.ParentNode.ParentNode.LeftChild)
{
temp &#61; node.ParentNode.ParentNode.RightChild;
if (temp !&#61; null && temp.Color &#61;&#61; NodeColor.Red)
{
node.ParentNode.Color &#61; NodeColor.Black;
temp.Color &#61; NodeColor.Black;
node.ParentNode.ParentNode.Color &#61; NodeColor.Red;
node &#61; node.ParentNode.ParentNode;
}
else
{
if (node &#61;&#61; node.ParentNode.RightChild)
{
node &#61; node.ParentNode;
LeftRotate(node);
}
node.ParentNode.Color &#61; NodeColor.Black;
node.ParentNode.ParentNode.Color &#61; NodeColor.Red;
RightRotate(node.ParentNode.ParentNode);
}
}
else
{
temp &#61; node.ParentNode.ParentNode.LeftChild;
if (temp !&#61; null && temp.Color &#61;&#61; NodeColor.Red)
{
node.ParentNode.Color &#61; NodeColor.Black;
temp.Color &#61; NodeColor.Black;
node.ParentNode.ParentNode.Color &#61; NodeColor.Red;
node &#61; node.ParentNode.ParentNode;
}
else
{
if (node &#61;&#61; node.ParentNode.LeftChild)
{
node &#61; node.ParentNode;
RightRotate(node);
}
node.ParentNode.Color &#61; NodeColor.Black;
node.ParentNode.ParentNode.Color &#61; NodeColor.Red;
LeftRotate(node.ParentNode.ParentNode);
}
}
}
root.Color &#61; NodeColor.Black;
}
///
/// Fix up tree property after delete node from tree
/// 1) node&#39;s sibling w is red;
/// 2) node&#39;s sibling w is black, and both of w&#39;s children are black;
/// 3) node&#39;s sibling w is black, w&#39;s left child is red, and w&#39;s right child is black;
/// 4) node&#39;s sibling w is black, and w&#39;s right child is red
///
///
private void DeleteFixup(RedBlackTreeNode<S> node,RedBlackTreeNode<S> parentNode)
{
RedBlackTreeNode<S> tempX &#61; null;
while (node !&#61; root && (node &#61;&#61; null||node.Color &#61;&#61; NodeColor.Black))
{
if (node &#61;&#61; parentNode.LeftChild)
{
tempX &#61; parentNode.RightChild;
if (tempX !&#61; null && tempX.Color &#61;&#61; NodeColor.Red)
{
tempX.Color &#61; NodeColor.Black;
node.ParentNode.Color &#61; NodeColor.Red;
LeftRotate(node.ParentNode);
}
else
{
if ((tempX.LeftChild &#61;&#61; null && tempX.RightChild &#61;&#61; null)
|| (tempX.LeftChild.Color &#61;&#61; NodeColor.Black && tempX.RightChild.Color &#61;&#61; NodeColor.Black))
{
tempX.Color &#61; NodeColor.Red;
node &#61; parentNode;
parentNode &#61; node.ParentNode;
}
else
{
if (tempX.RightChild &#61;&#61; null || tempX.RightChild.Color &#61;&#61; NodeColor.Black)
{
if (tempX.RightChild !&#61; null)
{
tempX.LeftChild.Color &#61; NodeColor.Black;
tempX.Color &#61; NodeColor.Red;
}
RightRotate(tempX);
tempX &#61; parentNode.RightChild;
}
tempX.Color &#61; parentNode.Color;
parentNode.Color &#61; NodeColor.Black;
tempX.RightChild.Color &#61; NodeColor.Black;
LeftRotate(parentNode);
node &#61; root;
}
}
}
else
{
tempX &#61; parentNode.LeftChild;
if (tempX !&#61; null && tempX.Color &#61;&#61; NodeColor.Red)
{
tempX.Color &#61; NodeColor.Black;
parentNode.Color &#61; NodeColor.Red;
RightRotate(parentNode);
}
else
{
if ((tempX.LeftChild &#61;&#61; null && tempX.RightChild &#61;&#61; null)
|| (tempX.LeftChild.Color &#61;&#61; NodeColor.Black && tempX.RightChild.Color &#61;&#61; NodeColor.Black))
{
tempX.Color &#61; NodeColor.Red;
node &#61; parentNode;
parentNode &#61; node.ParentNode;
}
else
{
if (tempX.RightChild &#61;&#61; null || tempX.RightChild.Color &#61;&#61; NodeColor.Black)
{
if (tempX.RightChild !&#61; null)
{
tempX.RightChild.Color &#61; NodeColor.Black;
tempX.Color &#61; NodeColor.Red;
}
LeftRotate(tempX);
tempX &#61; parentNode.LeftChild;
}
tempX.Color &#61; parentNode.Color;
parentNode.Color &#61; NodeColor.Black;
tempX.LeftChild.Color &#61; NodeColor.Black;
RightRotate(parentNode);
node &#61; root;
}
}
}
}
node.Color &#61; NodeColor.Black;
}
///
/// Right rotate the node, used when fix up tree property
///
///
private void RightRotate(RedBlackTreeNode<S> node)
{
if (node.LeftChild &#61;&#61; null)
return;
RedBlackTreeNode<S> child &#61; node.LeftChild;
if (node.ParentNode !&#61; null)
{
if (node.ParentNode.LeftChild !&#61; null && node.ParentNode.LeftChild &#61;&#61; node)
{
node.ParentNode.LeftChild &#61; child;
}
else
{
node.ParentNode.RightChild &#61; child;
}
}
else
{
node.LeftChild.ParentNode &#61; null;
}
node.LeftChild &#61; child.RightChild;
child.RightChild &#61; node;
RecheckRoot();
}
///
/// Left rotate the node, used when fix up tree property
///
///
private void LeftRotate(RedBlackTreeNode<S> node)
{
if (node.RightChild &#61;&#61; null)
return;
RedBlackTreeNode<S> child &#61; node.RightChild;
if (node.ParentNode !&#61; null)
{
if (node.ParentNode.LeftChild !&#61; null && node.ParentNode.LeftChild &#61;&#61; node)
{
node.ParentNode.LeftChild &#61; child;
}
else
{
node.ParentNode.RightChild &#61; child;
}
}
else
{
node.RightChild.ParentNode &#61; null;
}
node.RightChild &#61; child.LeftChild;
child.LeftChild &#61; node;
RecheckRoot();
}
///
/// the rotation may change the root, check and reset the root node.
///
private void RecheckRoot()
{
while (root.ParentNode !&#61; null)
{
root &#61; root.ParentNode;
}
}
}
}
namespace Cn.Linc.Algorithms.BasicStructure
{
public enum NodeColor
{
Black,
Red
}
///
/// A binary search tree is a red-black tree if it satisfies the following red-black properties:
/// 1) Every node is either red or black.
/// 2) The root is black.
/// 3) Every leaf (NIL) is black.
/// 4) If a node is red, then both its children are black.
/// 5) For each node, all paths from the node to descendant leaves contain the same number of black nodes.
///
/// Red-black trees are one of many search-tree schemes that are "balanced" in order to
/// guarantee that basic dynamic-set operations take O(lg n) time in the worst case.
///
/// Notice, a null leaf node or parent node is colored black.
///
/// More details please find in chapter 13, Introduction to Algorithms, Second Edition
/// by Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest and Clifford Stein ISBN:0262032937
/// The MIT Press © 2001 (1180 pages)
///
///
///
public class RedBlackTree<T,S>
where T: RedBlackTreeNode<S>
where S: IComparable
{
private RedBlackTreeNode<S> root;
///
/// Insert a new node, at first initialize the new node as red to keep the black height
/// rule of red black tree. Insert the new node to proper position accordding to its value,
/// the fix the tree according to the defination of red black tree.
///
///
public void InsertNode(S nodeValue)
{
RedBlackTreeNode<S> newNode &#61; new RedBlackTreeNode<S>(nodeValue);
if (root &#61;&#61; null)
{
root &#61; newNode;
}
else
{
RedBlackTreeNode<S> tempX &#61; root;
RedBlackTreeNode<S> tempY &#61; null;
while (tempX !&#61; null)
{
tempY &#61; tempX;
tempX &#61; nodeValue.CompareTo(tempX.Value) > 0 ? tempX.RightChild : tempX.LeftChild;
}
if (nodeValue.CompareTo(tempY.Value) >&#61; 0)
{
tempY.RightChild &#61; newNode;
}
else
{
tempY.LeftChild &#61; newNode;
}
}
InsertFixup(newNode);
}
///
/// Delete node.
/// If the node only have one or no child, just delete it.
/// If the node has both left and right children, find its successor, delete it and copy its
/// value to the node to be deleted.
/// After deleting, fix up the tree according to defination.
///
///
public void DeleteNode(T node)
{
if (node &#61;&#61; null)
return;
if ((node &#61;&#61; root) && (root.RightChild &#61;&#61; null) && (root.LeftChild &#61;&#61; null))
{
root &#61; null;
return;
}
RedBlackTreeNode<S> tempX &#61; null, tempY &#61; null;
if (node.LeftChild &#61;&#61; null || node.RightChild &#61;&#61; null)
{
tempY &#61; node;
}
else
{
tempY &#61; GetSuccessor(node);
}
tempX &#61; (tempY.LeftChild !&#61; null) ? tempY.LeftChild : tempY.RightChild;
if (tempY.ParentNode &#61;&#61; null)
root &#61; tempX;
else
{
if (tempY &#61;&#61; tempY.ParentNode.LeftChild)
{
tempY.ParentNode.LeftChild &#61; tempX;
}
else
{
tempY.ParentNode.RightChild &#61; tempX;
}
}
if (tempY !&#61; node)
{
node.Value &#61; tempY.Value;
}
// if black node is deleted the black height rule must be violated, fix it.
if (tempY.Color &#61;&#61; NodeColor.Black)
DeleteFixup(tempX,tempY.ParentNode);
}
///
/// Find the node with specified value.
///
/// specified value
///
public RedBlackTreeNode<S> FindNode(S value)
{
RedBlackTreeNode<S> temp &#61; root;
if (root &#61;&#61; null)
{
return null;
}
do
{
if(value.CompareTo(temp.Value)&#61;&#61;0)
{
return temp;
}
else if (temp.LeftChild !&#61; null && value.CompareTo(temp.Value) < 0)
{
temp &#61; temp.LeftChild;
}
else if (temp.RightChild !&#61; null && value.CompareTo(temp.Value) > 0)
{
temp &#61; temp.RightChild;
}
else
{
return null;
}
} while (true);
}
///
/// Find the successer of specific node,
/// if the right child is not empty, the successor is the far left node of the subtree.
/// If it has a successor and its right child is null, the successor must be the nearest
/// ancestor, and the left child of the successor is ancestor of the specific node.
///
/// the specific node
///
private RedBlackTreeNode<S> GetSuccessor(RedBlackTreeNode<S> currentNode)
{
RedBlackTreeNode<S> temp &#61; null;
if (currentNode.RightChild !&#61; null)
{
temp &#61; currentNode.RightChild;
while (temp.LeftChild !&#61; null)
{
temp &#61; temp.LeftChild;
}
return temp;
}
else
{
while (temp.ParentNode !&#61; null)
{
if (temp &#61;&#61; temp.ParentNode.LeftChild)
{
return temp.ParentNode;
}
else
{
temp &#61; temp.ParentNode;
}
}
return null;
}
}
///
/// Fix up red black tree after inserting node. Three cases:
/// 1) the uncle of the node is red;
/// 2) the uncle of the node is black and the node is right child(left rotate to case 3);
/// 3) the uncle of the node is black and the node is left child;
///
///
private void InsertFixup(RedBlackTreeNode<S> node)
{
RedBlackTreeNode<S> temp &#61; null;
while (node !&#61; root && node.ParentNode.Color &#61;&#61; NodeColor.Red)
{
if (node.ParentNode &#61;&#61; node.ParentNode.ParentNode.LeftChild)
{
temp &#61; node.ParentNode.ParentNode.RightChild;
if (temp !&#61; null && temp.Color &#61;&#61; NodeColor.Red)
{
node.ParentNode.Color &#61; NodeColor.Black;
temp.Color &#61; NodeColor.Black;
node.ParentNode.ParentNode.Color &#61; NodeColor.Red;
node &#61; node.ParentNode.ParentNode;
}
else
{
if (node &#61;&#61; node.ParentNode.RightChild)
{
node &#61; node.ParentNode;
LeftRotate(node);
}
node.ParentNode.Color &#61; NodeColor.Black;
node.ParentNode.ParentNode.Color &#61; NodeColor.Red;
RightRotate(node.ParentNode.ParentNode);
}
}
else
{
temp &#61; node.ParentNode.ParentNode.LeftChild;
if (temp !&#61; null && temp.Color &#61;&#61; NodeColor.Red)
{
node.ParentNode.Color &#61; NodeColor.Black;
temp.Color &#61; NodeColor.Black;
node.ParentNode.ParentNode.Color &#61; NodeColor.Red;
node &#61; node.ParentNode.ParentNode;
}
else
{
if (node &#61;&#61; node.ParentNode.LeftChild)
{
node &#61; node.ParentNode;
RightRotate(node);
}
node.ParentNode.Color &#61; NodeColor.Black;
node.ParentNode.ParentNode.Color &#61; NodeColor.Red;
LeftRotate(node.ParentNode.ParentNode);
}
}
}
root.Color &#61; NodeColor.Black;
}
///
/// Fix up tree property after delete node from tree
/// 1) node&#39;s sibling w is red;
/// 2) node&#39;s sibling w is black, and both of w&#39;s children are black;
/// 3) node&#39;s sibling w is black, w&#39;s left child is red, and w&#39;s right child is black;
/// 4) node&#39;s sibling w is black, and w&#39;s right child is red
///
///
private void DeleteFixup(RedBlackTreeNode<S> node,RedBlackTreeNode<S> parentNode)
{
RedBlackTreeNode<S> tempX &#61; null;
while (node !&#61; root && (node &#61;&#61; null||node.Color &#61;&#61; NodeColor.Black))
{
if (node &#61;&#61; parentNode.LeftChild)
{
tempX &#61; parentNode.RightChild;
if (tempX !&#61; null && tempX.Color &#61;&#61; NodeColor.Red)
{
tempX.Color &#61; NodeColor.Black;
node.ParentNode.Color &#61; NodeColor.Red;
LeftRotate(node.ParentNode);
}
else
{
if ((tempX.LeftChild &#61;&#61; null && tempX.RightChild &#61;&#61; null)
|| (tempX.LeftChild.Color &#61;&#61; NodeColor.Black && tempX.RightChild.Color &#61;&#61; NodeColor.Black))
{
tempX.Color &#61; NodeColor.Red;
node &#61; parentNode;
parentNode &#61; node.ParentNode;
}
else
{
if (tempX.RightChild &#61;&#61; null || tempX.RightChild.Color &#61;&#61; NodeColor.Black)
{
if (tempX.RightChild !&#61; null)
{
tempX.LeftChild.Color &#61; NodeColor.Black;
tempX.Color &#61; NodeColor.Red;
}
RightRotate(tempX);
tempX &#61; parentNode.RightChild;
}
tempX.Color &#61; parentNode.Color;
parentNode.Color &#61; NodeColor.Black;
tempX.RightChild.Color &#61; NodeColor.Black;
LeftRotate(parentNode);
node &#61; root;
}
}
}
else
{
tempX &#61; parentNode.LeftChild;
if (tempX !&#61; null && tempX.Color &#61;&#61; NodeColor.Red)
{
tempX.Color &#61; NodeColor.Black;
parentNode.Color &#61; NodeColor.Red;
RightRotate(parentNode);
}
else
{
if ((tempX.LeftChild &#61;&#61; null && tempX.RightChild &#61;&#61; null)
|| (tempX.LeftChild.Color &#61;&#61; NodeColor.Black && tempX.RightChild.Color &#61;&#61; NodeColor.Black))
{
tempX.Color &#61; NodeColor.Red;
node &#61; parentNode;
parentNode &#61; node.ParentNode;
}
else
{
if (tempX.RightChild &#61;&#61; null || tempX.RightChild.Color &#61;&#61; NodeColor.Black)
{
if (tempX.RightChild !&#61; null)
{
tempX.RightChild.Color &#61; NodeColor.Black;
tempX.Color &#61; NodeColor.Red;
}
LeftRotate(tempX);
tempX &#61; parentNode.LeftChild;
}
tempX.Color &#61; parentNode.Color;
parentNode.Color &#61; NodeColor.Black;
tempX.LeftChild.Color &#61; NodeColor.Black;
RightRotate(parentNode);
node &#61; root;
}
}
}
}
node.Color &#61; NodeColor.Black;
}
///
/// Right rotate the node, used when fix up tree property
///
///
private void RightRotate(RedBlackTreeNode<S> node)
{
if (node.LeftChild &#61;&#61; null)
return;
RedBlackTreeNode<S> child &#61; node.LeftChild;
if (node.ParentNode !&#61; null)
{
if (node.ParentNode.LeftChild !&#61; null && node.ParentNode.LeftChild &#61;&#61; node)
{
node.ParentNode.LeftChild &#61; child;
}
else
{
node.ParentNode.RightChild &#61; child;
}
}
else
{
node.LeftChild.ParentNode &#61; null;
}
node.LeftChild &#61; child.RightChild;
child.RightChild &#61; node;
RecheckRoot();
}
///
/// Left rotate the node, used when fix up tree property
///
///
private void LeftRotate(RedBlackTreeNode<S> node)
{
if (node.RightChild &#61;&#61; null)
return;
RedBlackTreeNode<S> child &#61; node.RightChild;
if (node.ParentNode !&#61; null)
{
if (node.ParentNode.LeftChild !&#61; null && node.ParentNode.LeftChild &#61;&#61; node)
{
node.ParentNode.LeftChild &#61; child;
}
else
{
node.ParentNode.RightChild &#61; child;
}
}
else
{
node.RightChild.ParentNode &#61; null;
}
node.RightChild &#61; child.LeftChild;
child.LeftChild &#61; node;
RecheckRoot();
}
///
/// the rotation may change the root, check and reset the root node.
///
private void RecheckRoot()
{
while (root.ParentNode !&#61; null)
{
root &#61; root.ParentNode;
}
}
}
}
RedBlackTreeNode.cs
using System;
namespace Cn.Linc.Algorithms.BasicStructure
{
public class RedBlackTreeNode<T> where T : IComparable
{
private T value;
public T Value
{
get { return this.value; }
set { this.value &#61; value; }
}
private NodeColor color;
public NodeColor Color
{
get { return color; }
set { color &#61; value; }
}
private RedBlackTreeNode<T> leftChild;
public RedBlackTreeNode<T> LeftChild
{
get { return leftChild; }
set
{
if (value !&#61; null)
value.ParentNode &#61; this;
leftChild &#61; value;
}
}
private RedBlackTreeNode<T> rightChild;
public RedBlackTreeNode<T> RightChild
{
get { return rightChild; }
set
{
if (value !&#61; null)
value.ParentNode &#61; this;
rightChild &#61; value;
}
}
private RedBlackTreeNode<T> parentNode;
public RedBlackTreeNode<T> ParentNode
{
get { return parentNode; }
set { parentNode &#61; value; }
}
public RedBlackTreeNode(T nodeValue)
{
value &#61; nodeValue;
color &#61; NodeColor.Red;
}
}
}
namespace Cn.Linc.Algorithms.BasicStructure
{
public class RedBlackTreeNode<T> where T : IComparable
{
private T value;
public T Value
{
get { return this.value; }
set { this.value &#61; value; }
}
private NodeColor color;
public NodeColor Color
{
get { return color; }
set { color &#61; value; }
}
private RedBlackTreeNode<T> leftChild;
public RedBlackTreeNode<T> LeftChild
{
get { return leftChild; }
set
{
if (value !&#61; null)
value.ParentNode &#61; this;
leftChild &#61; value;
}
}
private RedBlackTreeNode<T> rightChild;
public RedBlackTreeNode<T> RightChild
{
get { return rightChild; }
set
{
if (value !&#61; null)
value.ParentNode &#61; this;
rightChild &#61; value;
}
}
private RedBlackTreeNode<T> parentNode;
public RedBlackTreeNode<T> ParentNode
{
get { return parentNode; }
set { parentNode &#61; value; }
}
public RedBlackTreeNode(T nodeValue)
{
value &#61; nodeValue;
color &#61; NodeColor.Red;
}
}
}