数据结构,无外乎三:

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. Atitit 2016年attilax事业成就表

    Atitit 2016年attilax事业成就表 1.1. 项目管理模型---Rem模型2 1.2. 项目管理模型---vsi模型val specs implt3 1.3. 研发体系完善(gui与游戏 ...

  2. C#设计模式-中介者模式

    在现实生活中,有很多中介者模式的身影,例如QQ游戏平台,聊天室.QQ群和短信平台,这些都是中介者模式在现实生活中的应用,下面就具体分享下我对中介者模式的理解. 一. 中介者(Mediator)模式 从 ...

  3. Eclipse 使用技巧

    1.Eclipse 格式化代码时不换行与自动换行 Eclipse 推荐的编码风格默认是80列换行.每次用Eclipse自带的Ctrl+shift+f格式化代码时,如果原来的一行代码大于80列,Ecli ...

  4. 版本控制工具比较-CVS,SVN,GIT

    首先介绍几个版本控制软件相互比较的重要依据: a.版本库模型(Repository model):描述了多个源码版本库副本间的关系,有客户端/服务器和分布式两种模式.在客户端/服务器模式下,每一用户通 ...

  5. 第二章 consul的安装和启动

    安装环境: mac:64bit(查看mac位数:打开终端-->"uname -a") consul_0.6.4_darwin_amd64.zip和consul_0.6.4_w ...

  6. iOS开发——创建你自己的Framework

    如果你想将你开发的控件与别人分享,一种方法是直接提供源代码文件.然而,这种方法并不是很优雅.它会暴露所有的实现细节,而这些实现你可能并不想开源出来.此外,开发者也可能并不想看到你的所有代码,因为他们可 ...

  7. CSS3与页面布局学习总结(七)——前端预处理技术(Less、Sass、CoffeeScript、TypeScript)

    CSS不像其它高级语言一样支持算术运算.变量.流程控制与面向对象特性,所以CSS样式较多时会引起一些问题,如修改复杂,冗余,某些别的语言很简单的功能实现不了等.而javascript则是一种半面向对象 ...

  8. css预处理器sass使用教程(多图预警)

    css预处理器赋予了css动态语言的特性,如变量.函数.运算.继承.嵌套等,有助于更好地组织管理样式文件,以及更高效地开发项目.css预处理器可以更方便的维护和管理css代码,让整个网页变得更加灵活可 ...

  9. 详解web容器 - Jetty与Tomcat孰强孰弱

    Jetty 基本架构 Jetty目前的是一个比较被看好的 Servlet 引擎,它的架构比较简单,也是一个可扩展性和非常灵活的应用服务器.它有一个基本数据模型,这个数据模型就是 Handler(处理器 ...

  10. redis成长之路——(三)

    redis连接封装 StackExchange.Redis中有一些常功能是不在database对中,例如发布订阅.获取全部key(本代码中已封装到operation中了)等,而且StackExchan ...