数据结构,无外乎三:

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. [Java]Java日期及时间库插件 -- Joda Time.

    来到新公司工作也有一个多月了, 陆陆续续做了一些简单的项目. 今天做一个新东西的时候发现了 Joda Time的这个东西, 因为以前用的都是JDK原生的时间处理API, 大家都知道Java原生的时间处 ...

  2. iOS开发入门知识归纳

    一.iOS-C基础 二.iOS-Objective-C基础 三.iOS-Swift编程 三.iOS开发简单介绍 四.iOS-UI基础 1.UI控件介绍 2.UI布局-屏幕适配 五.iOS-多线程基础 ...

  3. iOS 之消息推送(个推)---个人小结

    前言:自从上个星期开始整这个推送,弄了差不多一个星期,今天终于给整好了,因此现在来记录这段"奇妙"的旅程. 我们公司使用的消息推送是用的第三方--个推,这里不得不说一下,个推的技术 ...

  4. 前端开发面试题收集(html部分)

    1.问:<keygen>是正确的HTML5标签吗? 答:是. <keygen> 标签规定用于表单的密钥对生成器字段.当提交表单时,私钥存储在本地,公钥发送到服务器. 2.问:& ...

  5. NotePad++中JSLint的使用

    1.第一步下载Notepad++ 2.安装JSLint插件 3.运行JSlint 4.前提是你设置了当前语言或者本身文件就是js 5.JSLint的作用主要就是检查你的JS的规则正确性(至少是绝大部分 ...

  6. 理清JavaScript正则表达式--上篇

    在JavaScript中,正则表达式由RegExp对象表示.RegExp对象呢,又可以通过直接量和构造函数RegExp两种方式创建,分别如下: //直接量 var re = /pattern/[g | ...

  7. 定时管理器框架-Task.MainForm

    入住博客园4年多了,一直都是看别人的博客,学习别人的知识,为各个默默无私贡献自己技术总结的朋友们顶一个:这几天突然觉得是时候加入该队列中,贡献出自己微弱的力量,努力做到每个月有不同学习总结,知识学习的 ...

  8. 非关系型数据库来了,CRL快速开发框架升级到版本4

    轮子?,我很任性,我要造不一样的轮子,同时支持关系型和非关系型的框架有没有 新版数据查询作了些调整,抽象了LabmdaQueryy和DBExtend,升级到版本4,非关系数据库MongoDB被支持了! ...

  9. 【Oracle 集群】ORACLE DATABASE 11G RAC 知识图文详细教程之RAC 工作原理和相关组件(三)

    RAC 工作原理和相关组件(三) 概述:写下本文档的初衷和动力,来源于上篇的<oracle基本操作手册>.oracle基本操作手册是作者研一假期对oracle基础知识学习的汇总.然后形成体 ...

  10. ASP.NET Core 中文文档 第四章 MVC(3.6.1 )Tag Helpers 介绍

    原文:Introduction to Tag Helpers 作者:Rick Anderson 翻译:刘浩杨 校对:高嵩(Jack) 什么是 Tag Helpers? Tag Helpers 提供了什 ...