x01.BSheepTree: 树
数据结构,无外乎三:
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: 树的更多相关文章
- Merkle Patricia Tree (MPT) 以太坊中的默克尔树
本篇博文是自己学习mpt的过程,边学边记录,很多原理性内容非自己原创,好的博文将会以链接形式进行共享. 一.什么是mpt MPT是以太坊中的merkle改进树,基于基数树,即前缀树改进而来,大大提高了 ...
- B树——算法导论(25)
B树 1. 简介 在之前我们学习了红黑树,今天再学习一种树--B树.它与红黑树有许多类似的地方,比如都是平衡搜索树,但它们在功能和结构上却有较大的差别. 从功能上看,B树是为磁盘或其他存储设备设计的, ...
- ASP.NET Aries 入门开发教程8:树型列表及自定义右键菜单
前言: 前面几篇重点都在讲普通列表的相关操作. 本篇主要讲树型列表的操作. 框架在设计时,已经把树型列表和普通列表全面统一了操作,用法几乎是一致的. 下面介绍一些差距化的内容: 1:树型列表绑定: v ...
- 再讲IQueryable<T>,揭开表达式树的神秘面纱
接上篇<先说IEnumerable,我们每天用的foreach你真的懂它吗?> 最近园子里定制自己的orm那是一个风生水起,感觉不整个自己的orm都不好意思继续混博客园了(开个玩笑).那么 ...
- HDU1671——前缀树的一点感触
题目http://acm.hdu.edu.cn/showproblem.php?pid=1671 题目本身不难,一棵前缀树OK,但是前两次提交都没有成功. 第一次Memory Limit Exceed ...
- 算法与数据结构(十一) 平衡二叉树(AVL树)
今天的博客是在上一篇博客的基础上进行的延伸.上一篇博客我们主要聊了二叉排序树,详情请戳<二叉排序树的查找.插入与删除>.本篇博客我们就在二叉排序树的基础上来聊聊平衡二叉树,也叫AVL树,A ...
- [C#] C# 知识回顾 - 表达式树 Expression Trees
C# 知识回顾 - 表达式树 Expression Trees 目录 简介 Lambda 表达式创建表达式树 API 创建表达式树 解析表达式树 表达式树的永久性 编译表达式树 执行表达式树 修改表达 ...
- bzoj3207--Hash+主席树
题目大意: 给定一个n个数的序列和m个询问(n,m<=100000)和k,每个询问包含k+2个数字:l,r,b[1],b[2]...b[k],要求输出b[1]~b[k]在[l,r]中是否出现. ...
- bzoj1901--树状数组套主席树
树状数组套主席树模板题... 题目大意: 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]--a[ ...
随机推荐
- sqlalchemy学习
sqlalchemy官网API参考 原文作为一个Pythoner,不会SQLAlchemy都不好意思跟同行打招呼! #作者:笑虎 #链接:https://zhuanlan.zhihu.com/p/23 ...
- 透视 HTML子元素的margin-top样式会应用在父元素上的原由
情况说明 当对页面中元素设置margin-top样式时,如果该元素有父元素,则margin-top会应用与父元素,子元素的top与父元素的top重叠.举例说明 <style>body{ma ...
- 慕课网H5圣诞主题
继七夕之后,我又出了一个圣诞主题的课程.圣诞主题是基于HTML5+CSS+JS编写与实现的,同时也是七夕主题的故事延续.圣诞主题依旧延续着七夕主题设计的思路,引入了3个经典的场景页面,在每个场景中表述 ...
- JavaScript版拼图小游戏
慕课网上准备开个新的jQuery教程,花了3天空闲时间写了一个Javascript版的拼图小游戏,作为新教程配套的分析案例 拼图游戏网上有不少的实现案例了,但是此源码是我自己的实现,所以不做太多的比较 ...
- .NET Core的文件系统[1]:读取并监控文件的变化
ASP.NET Core 具有很多针对文件读取的应用.比如我们倾向于采用JSON文件来定义配置,所以应用就会涉及针对配置文件读取.如果用户发送一个针对物理文件的HTTP请求,应用会根据指定的路径读取目 ...
- 你真的会玩SQL吗?实用函数方法汇总
你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...
- RFC4035笔记
章 节 标题 说明 补充说明 支持级别 1 介绍 1.定义DNSSEC协议修改点2.定义以下概念:已签名域(signed zone)和域签名的要求列表3.描述权威域名服务器为了处理签名域的行为变化4. ...
- JQuery的核心的一些方法[扒来的]
JQuery的核心的一些方法 each(callback) '就像循环 $("Element").length; ‘元素的个数,是个属性 $("Element" ...
- php函数强大的 strtotime
使用strtotime可以将各种格式的时间字符串转换为时间戳 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 转换常规时间格式 echo date('Y-m-d H:i: ...
- SVNKit支持SSH连接
SVNKit这个开源工具,用于Java语言访问SVN库,咋看的时候很方便,其实坑特别多.我在这里只想跟大家说一句,如果你还没有用过,请不要在生产环境使用这个东西了,兼容性问题搞死你(替换方案是直接用s ...