在下小白一个 如有错误请指正
上代码
using System;
//数据结构
namespace DataStructure
{
public enum ColorType
{
Black = 0,
Red,
}
///
/// 红黑树节点
///
///
public class RedBlackNode
{
public RedBlackNode(T key, RedBlackNode
ColorType color)
: base(key, parentNode, rightNode, leftNode)
{
Mcolor = color;
ParentNode = parentNode;
LeftChildNodes = leftNode;
RightChildNodes = rightNode;
}
}
///
/// 红黑树
/// 特性
///(1) 每个节点或者是黑色,或者是红色。
///(2) 根节点是黑色。
///(3) 每个叶子节点是黑色。 [注意:这里叶子节点,是指为空的叶子节点!]
///(4) 如果一个节点是红色的,则它的子节点必须是黑色的。
///(5) 从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。
///
public class RedBlackTree
{
///
/// 获取父节点
///
///
///
private RedBlackNode
{
return (RedBlackNode
}
///
/// 获取颜色
///
///
///
private ColorType GetColor(RedBlackNode
{
if (node == null)
return ColorType.Black;
return node.Mcolor == ColorType.Black ? ColorType.Black : ColorType.Red;
}
///
/// 设置父节点
///
///
///
///
private RedBlackNode
{
return node == null ? null : parent;
}
///
/// 设置颜色为红色
///
///
private void SetRed(RedBlackNode
{
if (node != null)
node.Mcolor = ColorType.Red;
}
///
/// 设置颜色为黑色
///
///
private void SetBlack(RedBlackNode
{
if (node != null)
node.Mcolor = ColorType.Black;
}
///
/// 判断是否为红色
///
///
///
private bool IsRed(RedBlackNode
{
if (node == null)
return false;
return node.Mcolor == ColorType.Red ? true : false;
}
///
/// 判断是否是黑色
///
///
///
private bool IsBlack(RedBlackNode
{
if (node == null)
return true;
return node.Mcolor == ColorType.Black ? true : false;
}
///
/// 设置节点颜色
///
///
///
private void SetColor(RedBlackNode
{
if (node != null)
node.Mcolor = color;
}
///
/// 左旋
///
///
private void LeftRotate(RedBlackNode
{
RedBlackNode
rootNode.RightChildNodes = tempNode.LeftChildNodes;
if (tempNode.LeftChildNodes != null)
tempNode.LeftChildNodes.ParentNode = rootNode;
tempNode.ParentNode = rootNode.ParentNode;
if (rootNode.ParentNode == null)
this.MRoot = tempNode;
else
{
if (rootNode.ParentNode.LeftChildNodes == rootNode)
rootNode.ParentNode.LeftChildNodes = tempNode;
else
rootNode.ParentNode.RightChildNodes = tempNode;
}
tempNode.LeftChildNodes = rootNode;
rootNode.ParentNode = tempNode;
}
///
/// 右旋
///
///
private void RightRotate(RedBlackNode
{
RedBlackNode
rootNode.LeftChildNodes = tempNode.RightChildNodes;
if (tempNode.RightChildNodes != null)
tempNode.RightChildNodes.ParentNode = rootNode;
tempNode.ParentNode = rootNode.ParentNode;
if (rootNode.ParentNode == null)
{
this.MRoot = tempNode;
}
else
{
if (rootNode == rootNode.ParentNode.LeftChildNodes)
{
rootNode.ParentNode.LeftChildNodes = tempNode;
}
else
{
rootNode.ParentNode.RightChildNodes = tempNode;
}
}
tempNode.RightChildNodes = rootNode;
rootNode.ParentNode = tempNode;
}
///
/// 插入节点
/// 把插入的节点修改为红色
/// 因为插入红色的节点更不容易违反红黑树的特性
/// 只是有可能违反第四条,这样只要处理使它不违反第四条就行了
///
/// 要插入的节点
public override void InsetNode(T key)
{
//将插入的节点修改为红色
RedBlackNode
//使用二叉查找树的插入
InsetNode(this, node);
}
///
/// 插入节点
///
///
///
protected void InsetNode(RedBlackTree
{
base.InsetNode(tree, node1);
node1.Mcolor = ColorType.Red;
FixUpInsetNode(node1);
}
///
/// 红黑树插入修正函数
/// 通过插入可能破坏了红黑树的结构 重新整理结构
///
///
private void FixUpInsetNode(RedBlackNode
{
RedBlackNode
while ((parent = ParentOf(node)) != null && IsRed(parent))
{
gParent = ParentOf(parent);
//父节点是左节点
if (parent == gParent.LeftChildNodes)
{
RedBlackNode
//三种插入情况
//1.叔叔节点?不为空 且为红色
if (uncle != null && IsRed(uncle))
{
// 假设当前二叉树是这样: g(黑) 修正之后 g(n 红)
// / \ / \
// (红)p u(红) (黑)p u(黑)
// / /
// n(黑) n(黑)
//设置叔叔节点和父节点为红色 祖父节点为黑色
SetBlack(uncle);
SetBlack(parent);
SetRed(gParent);
//从下往上调整
node = gParent;
continue;
}
//2.叔叔节点 为黑色 且当前节点为右节点
if (parent.RightChildNodes == node)
{
// 假设当前二叉树是这样: g(黑) 修正之后 g(黑)
// / \ / \
// (红)p u(黑) (黑)n u(黑)
// \ /
// n(黑) p(红)
RedBlackNode
//左旋 把父节点旋转为当前节点的左节点 当前节点旋转到之前父节点的位置
LeftRotate(parent);
temp = parent;
parent = node;
node = temp;
}
//3.叔叔节点是黑色 且当前节点是左节点
// 假设当前二叉树是这样: g(黑) 修正之后 p(黑)
// / \ \
// (红)p u(黑) g(红)
// / / \
// n(黑) (黑)n u(黑)
SetBlack(parent);
SetRed(gParent);
RightRotate(gParent);
}
else //父节点是右节点
{
RedBlackNode
//叔叔节点是红
if (uncle != null && IsRed(uncle))
{
// 假设当前二叉树是这样: g(黑) 修正之后 g(n 红)
// / \ / \
// (红)u p(红) (黑)u p(黑)
// / /
// n(黑) n(黑)
SetBlack(uncle);
SetBlack(parent);
SetRed(gParent);
node = gParent;
continue;
}
//叔叔节点是黑 且当前节点是左节点
if (node == parent.LeftChildNodes)
{
// 假设当前二叉树是这样: g(黑) 修正之后 g(黑)
// / \ / \
// (红)u p(黑) (黑)u n(黑)
// / \
// n(黑) p(红)
RedBlackNode
RightRotate(parent);
temp = parent;
parent = node;
node = temp;
}
//叔叔节点是黑 且当前节点是右节点
// 假设当前二叉树是这样: g(黑) 修正之后 p(黑)
// / \ /
// (黑)u p(红) g(红)
// \ / \
// n(黑) (黑)u n(黑)
SetRed(gParent);
SetBlack(parent);
LeftRotate(gParent);
}
}
SetBlack((RedBlackNode
}
///
/// 删除节点
///
/// 删除的节点
///
/// 1.被删除节点的左右子节点都不为空 寻找该节点的后继(取代)节点(大于该节点的最小节点)取代该节点
/// (1)要删除的节点是根节点
/// (2)要删除的节点不是根节点
/// (3)要删除的节点的后继节点是他的子节点
/// 2.要删除的节点的左节点或者右节点为空
private void RemoveNode(RedBlackNode
{
RedBlackNode
ColorType color;
if (removeNode.LeftChildNodes != null && removeNode.RightChildNodes != null)
{
RedBlackNode
replaceNode = replaceNode.RightChildNodes as RedBlackNode
//寻找后继结点 红黑二叉树是有序的 所以可以这样寻找他的后继节点
while (replaceNode.LeftChildNodes != null)
replaceNode = replaceNode.LeftChildNodes as RedBlackNode
//判断要删除的节点是否是根节点
if (ParentOf(removeNode) != null)
{
//如果要删除的节点是左节点
if (ParentOf(removeNode).LeftChildNodes == removeNode)
{
ParentOf(removeNode).LeftChildNodes = replaceNode;
}
else
{
ParentOf(removeNode).RightChildNodes = replaceNode;
}
}
else
{
this.MRoot = replaceNode;
}
//取代节点不存在左节点 因为replaceNode是后继节点 且 红黑二叉树是有序的
childNode = replaceNode.RightChildNodes as RedBlackNode
parentNode = replaceNode.ParentNode as RedBlackNode
color = GetColor(replaceNode);
//如果被删除的节点是取代节点的父节点
if (parentNode == removeNode)
{
parentNode = replaceNode;
}
else
{
if (childNode != null)
childNode.ParentNode = parentNode;
parentNode.LeftChildNodes = childNode;
replaceNode.RightChildNodes = removeNode.RightChildNodes;
SetParent((RedBlackNode
}
replaceNode.ParentNode = removeNode.ParentNode;
//此处处理颜色 取代节点移动到的位置节点颜色不会发生混乱
replaceNode.Mcolor = removeNode.Mcolor;
replaceNode.LeftChildNodes = removeNode.LeftChildNodes;
removeNode.LeftChildNodes.ParentNode = removeNode;
//如果replaceNode为黑色 则它移走后他的子节点和父节点拼接后可能出现两个都是红
//可能会违反 特性 2. 4. 5
if (color == ColorType.Black)
{
//修正
FixUpRemove(childNode, parentNode);
}
removeNode = null;
return;
}
//如果要删除的右节点为空
if (removeNode.LeftChildNodes != null)
{
childNode = removeNode.LeftChildNodes as RedBlackNode
}
else //要删除的左节点为空
{
childNode = removeNode.RightChildNodes as RedBlackNode
}
parentNode = removeNode.ParentNode as RedBlackNode
color = removeNode.Mcolor;
//获取要删除的节点的子节点
if (childNode != null)
childNode.ParentNode = parentNode;
//判断要删除的节点是否是根节点
if (parentNode != null)
{
//如果要删除的节点是左节点
if (removeNode == parentNode.LeftChildNodes)
{
//父节点的左节点为子节点
parentNode.LeftChildNodes = childNode;
}
else
{
parentNode.RightChildNodes = childNode;
}
}
else
this.MRoot = childNode;
//如果要删除的为黑色
//如果replaceNode为黑色 则它移走后他的子节点和父节点拼接后可能出现两个都是红
//可能会违反 特性 2. 4. 5
if (color == ColorType.Black)
{
FixUpRemove(childNode, parentNode);
}
removeNode = null;
}
///
/// 删除修正方法
/// 从红黑树删除节点后 红黑树失去平衡 使用此方法修正
///
///
///
private void FixUpRemove(RedBlackNode
{
RedBlackNode
while ((childNode == null || IsBlack(childNode)) && childNode != this.MRoot)
{
if (childNode == parent.LeftChildNodes)
{
brotherNode = parent.RightChildNodes as RedBlackNode
//四种删除
//1.childNode的兄弟节点是红色 通过染黑兄弟节点和旋转 转化为兄弟节点为黑色的问题
if (IsRed(brotherNode))
{
SetBlack(brotherNode);
SetRed(parent);
LeftRotate(parent);
brotherNode = parent.RightChildNodes as RedBlackNode
}
//2.兄弟节点为黑色且兄弟节点的子节点也为黑色 此时通过自己节点到父节点 和通过兄弟节点到父节点经过的黑色节点数量不同 违反了特性五
if ((brotherNode.LeftChildNodes == null || IsBlack((RedBlackNode
(brotherNode.RightChildNodes == null || IsBlack((RedBlackNode
{
SetRed(brotherNode);
childNode = parent;
parent = ParentOf(parent);
}
else
{
//3.兄弟节点是黑色 兄弟的左子节点是红色右子节点是黑色 转化为第四种情况 且不破坏 特性五
if (brotherNode.RightChildNodes == null ||
IsBlack((RedBlackNode
{
SetBlack((RedBlackNode
SetRed(brotherNode);
RightRotate(brotherNode);
brotherNode = parent.RightChildNodes as RedBlackNode
}
//4.兄弟节点是黑色 兄弟节点的右子节点是红色 左子节点是任意颜色
//把兄弟节点染成父节点的颜色
SetColor(brotherNode, GetColor(parent));
//把父节点染成黑色
SetBlack(parent);
//把兄弟节点的右节点染成黑色
SetBlack((RedBlackNode
//对当前父节点进行左旋
LeftRotate(parent);
childNode = this.MRoot as RedBlackNode
break;
}
}
else
{
brotherNode = parent.LeftChildNodes as RedBlackNode
if (IsRed(brotherNode))
{
SetRed(parent);
SetBlack(brotherNode);
RightRotate(parent);
brotherNode = parent.LeftChildNodes as RedBlackNode
}
if ((brotherNode.LeftChildNodes == null || IsBlack((RedBlackNode
(brotherNode.RightChildNodes == null || IsBlack((RedBlackNode
{
SetRed(brotherNode);
childNode = parent;
parent = parent.ParentNode as RedBlackNode
}
else
{
if (brotherNode.LeftChildNodes == null || IsBlack((RedBlackNode
{
SetRed(brotherNode);
SetBlack((RedBlackNode
LeftRotate(brotherNode);
brotherNode = parent.LeftChildNodes as RedBlackNode
}
SetColor(brotherNode, GetColor(parent));
SetBlack(parent);
SetBlack((RedBlackNode
RightRotate(parent);
childNode = this.MRoot as RedBlackNode
break;
}
}
}
if (childNode != null)
SetBlack(childNode);
}
public override void RemoveNode(T key)
{
RemoveNode(FindNode(key, (RedBlackNode
}
public RedBlackNode
{
if (treeNode == null)
{
return null;
}
int comparable = key.CompareTo(treeNode.MKey);
if (comparable < 0)
{
return FindNode(key, (RedBlackNode
}
else if (comparable > 0)
{
return FindNode(key, (RedBlackNode
}
else
{
return treeNode;
}
}
private void print(TreeNode
{
if (tree != null)
{
if (direction == 0) // tree是根节点
Console.WriteLine("{0} is root This color is:{1}", tree.MKey, tree.Mcolor);
else // tree是分支节点
Console.WriteLine("{0} is {1}'s This color is:{2}", tree.MKey, key, tree.Mcolor);
print(tree.LeftChildNodes, tree.MKey, -1);
print(tree.RightChildNodes, tree.MKey, 1);
}
}
public void print()
{
if (MRoot != null)
print(MRoot, MRoot.MKey, 0);
}
}
}