数据结构,无外乎三:

1. 一对一,线性表,数组是也;

2. 一对多,树,菜单是也;

3. 多对多,图,网络是也。

涉及到树,有一个平衡的问题,左旋转,右旋转,转得人晕晕乎乎。好在陈广的《数据结构C#描述》讲解非常详尽,值得一读。对照该书的例子,采用反编译的手段,写了个小程序,主要的目的是为了学习方便,也便于自己查找复习,无他。源代码可到置顶随笔 x01.Download => book => 2016 中下载:x01.BSheepTree.zip;其运行效果图如下:

略作修改,便成为红黑树,解释参看:红黑树 其运行效果图如下:

关键代码如下:

/**
* RedBlackTree.cs (c) 2015 by x01
*/
using System;
using System.Diagnostics;
using System.Text; namespace x01.BSheepTree
{
/// <summary>
/// Description of RedBlackTree.
/// </summary>
public class RedBlackTree : IBinaryTree
{
public static readonly bool Red = true;
public static readonly bool Black = false; public class RNode : INode
{
public int Key { get; set; }
public int Value { get; set; }
public RNode Parent { get; set; }
public RNode Left { get; set; }
public RNode Right { get; set; }
public RNode Sibling
{
get {
RNode sibling = null;
if (Parent != null && this == Parent.Left)
sibling = Parent.Right;
else if (Parent != null && this == Parent.Right)
sibling = Parent.Left;
return sibling;
}
}
public RNode GrandParent
{
get {
if (Parent != null)
return Parent.Parent;
return null;
}
}
public RNode Uncle
{
get {
RNode uncle = null;
if (GrandParent != null) {
if (Parent == GrandParent.Left)
uncle = GrandParent.Right;
else if (Parent == GrandParent.Right)
uncle = GrandParent.Left;
}
return uncle;
}
}
public bool Color { get; set; } public RNode(int key, int value)
{
this.Key = key;
this.Value = value;
Color = Red;
Parent = Left = Right = null;
} public RNode LeftMost
{
get {
var node = this;
while (node != null && node.Left != null ) {
node = node.Left;
}
return node;
}
} public int Data {
get {
return (int)Value;
}
} INode INode.Left {
get {
return (INode)Left;
}
} INode INode.Right {
get {
return (INode)Right;
}
}
} RNode root = null; public void Insert(int key, int value)
{
root = Insert(root, key, value);
root.Color = Black;
//SetParent();
}
RNode Insert(RNode node, int key, int value)
{
if (node == null)
return new RNode(key, value);
int cmp = key.CompareTo(node.Key);
if (cmp < )
node.Left = Insert(node.Left, key, value);
else if (cmp > )
node.Right = Insert(node.Right, key, value);
else
node.Value = value; node = Balance(node); return node;
} RNode Balance(RNode node)
{
if (node != null) {
if (IsRed(node.Right) && !IsRed(node.Left)) node = RotateLeft(node);
if (IsRed(node.Left) && IsRed(node.Left.Left)) node = RotateRight(node);
if (IsRed(node.Left) && IsRed(node.Right)) FlipColor(node);
}
return node;
} void SetParent()
{
SetParent(root);
}
void SetParent(RNode node)
{
if (node != null) {
if (node.Left != null) {
node.Left.Parent = node;
SetParent(node.Left);
}
if (node.Right != null) {
node.Right.Parent = node;
SetParent(node.Right);
}
}
} void Replace(RNode oldNode, RNode newNode)
{
if (oldNode == null || newNode == null)
throw new Exception(); oldNode.Key = newNode.Key;
oldNode.Value = newNode.Value;
} public RNode GetNode(int key)
{
return GetNode(root, key);
}
RNode GetNode(RNode node, int key)
{
while (node != null) {
int cmp = key.CompareTo(node.Key);
if (cmp < ) node = node.Left;
else if (cmp > ) node = node.Right;
else return node;
}
return null;
} public bool IsEmpty { get { return root == null; } } public void DeleteMin()
{
if (IsEmpty) return;
if (!IsRed(root.Left) && !IsRed(root.Right))
root.Color = Red;
root = DeleteMin(root);
if (!IsEmpty) root.Color = Black;
} RNode DeleteMin(RNode node)
{
if (node != null && node.Left == null)
return null; if (!IsRed(node.Left) && !IsRed(node.Left.Left))
node = MoveRedLeft(node); node.Left = DeleteMin(node.Left); return Balance(node);
} RNode MoveRedLeft(RNode node)
{
FlipColor(node);
if (IsRed(node.Right.Left)) {
node.Right = RotateRight(node.Right);
node = RotateLeft(node);
FlipColor(node);
}
return node;
} RNode MoveRedRight(RNode node)
{
FlipColor(node);
if (IsRed(node.Left.Left)) {
node = RotateRight(node);
FlipColor(node);
}
return node;
} public void DeleteMax()
{
if (IsEmpty) throw new Exception();
if (!IsRed(root.Left) && !IsRed(root.Right))
root.Color = Red;
root = DeleteMax(root);
if (!IsEmpty) root.Color = Black;
} RNode DeleteMax(RNode node)
{
if (IsRed(node.Left))
node = RotateRight(node);
if (node.Right == null)
return null;
if (!IsRed(node.Right) && !IsRed(node.Right.Left))
node = MoveRedRight(node);
node.Right = DeleteMax(node.Right);
return Balance(node);
} public void Delete(int key)
{
var node = GetNode(key);
if (node == null) return; if (!IsRed(node.Left) && !IsRed(node.Right))
root.Color = Red; root = Delete(root, key);
if (!IsEmpty) root.Color = Black;
} RNode Delete(RNode node, int key)
{
if (key.CompareTo(node.Key) < ) {
if (!IsRed(node.Left) && !IsRed(node.Left.Left))
node = MoveRedLeft(node);
node.Left = Delete(node.Left, key);
} else {
if (IsRed(node.Left))
node = RotateRight(node);
if (key.CompareTo(node.Key) == && node.Right == null)
return null;
if (!IsRed(node.Right) && !IsRed(node.Right.Left))
node = MoveRedRight(node);
if (key.CompareTo(node.Key) == ) {
var x = Min(node.Right);
node.Key = x.Key;
node.Value = x.Value;
node.Right = DeleteMin(node.Right);
} else {
node.Right = Delete(node.Right, key);
}
}
return Balance(node);
} RNode Min(RedBlackTree.RNode node)
{
if (node.Left == null) return node;
else return Min(node.Left);
} void FlipColor(RNode node)
{
node.Color = !node.Color;
node.Left.Color = !node.Left.Color;
node.Right.Color = !node.Right.Color;
} RNode RotateRight(RNode node)
{
RNode left = node.Left;
node.Left = left.Right;
left.Right = node;
left.Color = node.Color;
node.Color = Red;
return left;
} RNode RotateLeft(RNode node)
{
RNode right = node.Right;
node.Right = right.Left;
right.Left = node;
right.Color = node.Color;
node.Color = Red;
return right;
} bool IsRed(RNode node)
{
return node != null && node.Color == Red;
} public int Count
{
get { return _Count(root); }
}
int _Count(RNode node)
{
if (node != null)
return _Count(node.Left) + _Count(node.Right) + ;
return ;
} #region Test void Print()
{
Print(root);
}
void Print(RNode node)
{
if (node != null) {
string clr = node.Color ? "R" : "B";
Console.Write("{0}{1} => ", node.Key, clr);
Print(node.Left);
Print(node.Right);
}
}
internal static void Test()
{
var tree = new RedBlackTree();
for (int i = ; i < ; i++) {
tree.Insert(i,i);
}
tree.Delete();
tree.Print();
Console.WriteLine();
} public INode Head {
get {
return (INode)root;
}
}
public bool Add(int data)
{
Insert((int)data, (int)data);
return true;
}
public bool Remove(int data)
{
Delete((int)data);
return true;
} #endregion
}
}

RedBlackTree.cs

x01.BSheepTree: 树的更多相关文章

  1. Merkle Patricia Tree (MPT) 以太坊中的默克尔树

    本篇博文是自己学习mpt的过程,边学边记录,很多原理性内容非自己原创,好的博文将会以链接形式进行共享. 一.什么是mpt MPT是以太坊中的merkle改进树,基于基数树,即前缀树改进而来,大大提高了 ...

  2. B树——算法导论(25)

    B树 1. 简介 在之前我们学习了红黑树,今天再学习一种树--B树.它与红黑树有许多类似的地方,比如都是平衡搜索树,但它们在功能和结构上却有较大的差别. 从功能上看,B树是为磁盘或其他存储设备设计的, ...

  3. ASP.NET Aries 入门开发教程8:树型列表及自定义右键菜单

    前言: 前面几篇重点都在讲普通列表的相关操作. 本篇主要讲树型列表的操作. 框架在设计时,已经把树型列表和普通列表全面统一了操作,用法几乎是一致的. 下面介绍一些差距化的内容: 1:树型列表绑定: v ...

  4. 再讲IQueryable<T>,揭开表达式树的神秘面纱

    接上篇<先说IEnumerable,我们每天用的foreach你真的懂它吗?> 最近园子里定制自己的orm那是一个风生水起,感觉不整个自己的orm都不好意思继续混博客园了(开个玩笑).那么 ...

  5. HDU1671——前缀树的一点感触

    题目http://acm.hdu.edu.cn/showproblem.php?pid=1671 题目本身不难,一棵前缀树OK,但是前两次提交都没有成功. 第一次Memory Limit Exceed ...

  6. 算法与数据结构(十一) 平衡二叉树(AVL树)

    今天的博客是在上一篇博客的基础上进行的延伸.上一篇博客我们主要聊了二叉排序树,详情请戳<二叉排序树的查找.插入与删除>.本篇博客我们就在二叉排序树的基础上来聊聊平衡二叉树,也叫AVL树,A ...

  7. [C#] C# 知识回顾 - 表达式树 Expression Trees

    C# 知识回顾 - 表达式树 Expression Trees 目录 简介 Lambda 表达式创建表达式树 API 创建表达式树 解析表达式树 表达式树的永久性 编译表达式树 执行表达式树 修改表达 ...

  8. bzoj3207--Hash+主席树

    题目大意: 给定一个n个数的序列和m个询问(n,m<=100000)和k,每个询问包含k+2个数字:l,r,b[1],b[2]...b[k],要求输出b[1]~b[k]在[l,r]中是否出现. ...

  9. bzoj1901--树状数组套主席树

    树状数组套主席树模板题... 题目大意: 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]--a[ ...

随机推荐

  1. 网站使用https协议

    了解https HTTPS 是以安全为目标的 HTTP 通道,即 HTTP 下加入 SSL 加密层.HTTPS 不同于 HTTP 的端口,HTTP默认端口为80,HTTPS默认端口为443. SSL ...

  2. iOS-推送,证书申请,本地推送

    介绍一点点背景资料 众所周知,使用推送通知是一个很棒的.给应用添加实时消息通知的方式.这样做的结局是,开发者和用户之间,彼此永远保持着一种令人愉悦的亲密关系. 然而不幸的是,iOS的推送通知并非那么容 ...

  3. Python 资源大全中文版

    Python 资源大全中文版 我想很多程序员应该记得 GitHub 上有一个 Awesome - XXX 系列的资源整理.awesome-python 是 vinta 发起维护的 Python 资源列 ...

  4. 初始Bootstrap

    使用示例 ①下载Bootstrap框架 网址:http://v3.bootcss.com/getting-started/#download ②解压得到三个文件     ③将文件添加进项目后,在页面中 ...

  5. 计算机程序的思维逻辑 (29) - 剖析String

    上节介绍了单个字符的封装类Character,本节介绍字符串类.字符串操作大概是计算机程序中最常见的操作了,Java中表示字符串的类是String,本节就来详细介绍String. 字符串的基本使用是比 ...

  6. RHEL6.4 + Oracle 11g DG测试环境快速搭建参考

    环境现状: 两台虚拟主机A和B: 1. A机器已安装ASM存储的Oracle 11g 实例      参考:http://www.cnblogs.com/jyzhao/p/4332410.html 2 ...

  7. 探究负边距(negative margin)原理

    W3C规范在介绍margin时有这样一句话: Negative values for margin properties are allowed, but there may be implement ...

  8. MyCat源码分析系列之——SQL下发

    更多MyCat源码分析,请戳MyCat源码分析系列 SQL下发 SQL下发指的是MyCat将解析并改造完成的SQL语句依次发送至相应的MySQL节点(datanode)的过程,该执行过程由NonBlo ...

  9. Performance Monitor3:监控SQL Server的内存压力

    SQL Server 使用的资源受到操作系统的调度,同时,SQL Server在内部实现了一套调度算法,用于管理从操作系统获取的资源,主要是对内存和CPU资源的调度.一个好的数据库系统,必定在内存中缓 ...

  10. ASP.NET Core 静态文件及JS包管理器(npm, Bower)的使用

    在 ASP.NET Core 中添加静态文件 虽然ASP.NET主要大都做着后端的事情,但前端的一些静态文件也是很重要的.在ASP.NET Core中要启用静态文件,需要Microsoft.AspNe ...