各种语言环境的二叉树、红黑树教程多得很,但是看来看去,它们好像来自于一个版本——Wiki百科版,连图都是一样的,所以原理和伪代码不如直接看维基百科,Wikipedia——红黑树,Wikipedia——二叉搜索树(如果你没有梯子,我上传了一份PDF文件,点击下载PDF文件),我感觉Wiki百科上讲的已经很清楚了,准确的说,比各种复制粘贴的清楚的多,至少排版什么的很清楚,每个点讲的也比较有条理。
二叉树只要学过数据结构就一定知道,但是数据结构主要讲了算法,实现部分一带而过,维基百科中已经给出了主要伪代码,我们只需要整合成我们用的变成语言就可以了,红黑树是重头戏
在这里我给大家一个关于红黑树的概念,想真正掌握,务必详读Wikipedia
关于二叉树和红黑树:
- 红黑树是对二叉树的优化,使树的查找效率更加稳定(二叉树最坏情况下,当先后插入的关键字有序时,构成的二叉查找树蜕变为单支树,和链表就没什么区别了,优势消失)
- 红黑树和二叉树在查找、遍历、获取最大值最小值、销毁树等操作上是完全一样的
- 红黑树与二叉树在实现上的主要区别就是,插入与删除之后的修正操作(维护红黑树的5个规则)
5个规则:
1.节点是红色或黑色。
2.根是黑色。
3.所有叶子都是黑色(叶子是NIL节点)。
4.每个红色节点必须有两个黑色的子节点。(从每个叶子到根的所有路径上不能有两个连续的红色节点。)
5.从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点。
红黑树的3个维护手段:
- 变色
插入一个新节点(插入节点初始颜色必然为红色,关于为什么,wiki讲的很清楚)
插入节点的父节点为红色(现在违反了规则4)
我们应该把当前节点改为黑色
这里只是举个例子,各种复杂情况在wiki里已经详细讲解 - 左旋
- 右旋
我感觉搞一个东西之前,wiki是必看的,如果文档质量高看了不亏,而且常常能在最后引用和外链中找到好东西。在wiki红黑树文档中,详解了红黑树插入删除的各种情况,并且给出了C++实例,看完肯定能掌握。
使用tree类
在A*寻路在unity2d中的应用中,提到了A*寻路有在Openlist中寻找最优格子,当时图省事连快速排序都没用,直接硬排的,这里完全可以用红黑树替代,格子划分越多,性能提升越明显(顺便一提,路线平滑可以用贝塞尔曲线拟合,这样应该可以写出完美版本的A *寻路),首先我们把这个类封装成dll
在存储类的文件夹\tree\bin\Debug中,可以找到tree.dll文件
将tree.dll文件拖到Assets\Plugins文件夹下
这里需要注意一个.net版本号问题,需要对应
现在我们可以在unity中方便的用二叉树和红黑树存储数据了
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using tree;//引用tree
public class usetree : MonoBehaviour {
// Use this for initialization
void Start () {
//新建二叉树,data为泛型,这里以transform为例
BinaryTree<Transform> A = new BinaryTree<Transform>();
//添加数据
A.insert((int)10, this.transform);
//获取最大值
BNode<Transform> a1;
a1 = A.maxNode();
//获取最小值
a1 = A.minNode();
//查找
a1 = A.find((int)10);
//获取升序
List<Transform> list_1 = new List<Transform>();
A.traverse(0, list_1);
//获取降序
A.traverse(2, list_1);
//中向遍历
A.traverse(1, list_1);
//删除
bool delornot=A.delete((int)10);//delete会返回一个bool,检查是否成功删除
//*删除最大值
A.delete(A.maxNode().key);
//销毁树
A.clear();
//销毁分支
A.destroy(A.find((int)10));
}
}
tree中一共有4个类,BNode,BinaryTree,RBNode和RBTree,在操作上,红黑树和二叉树一样。
以下是tree的全部代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace tree
{
public class BinaryTree<T1>
{
private BNode<T1> root;//根
public BinaryTree(){
root = null;
}
//查询
public BNode<T1> maxNode()
{
BNode<T1> current = root;
BNode<T1> parent = root;
while(current != null)
{
parent = current;
current = current.rightchild;
}
return parent;
}
public BNode<T1> minNode()
{
BNode<T1> current = root;
BNode<T1> parent = root;
while (current != null)
{
parent = current;
current = current.leftchild;
}
return parent;
}
public BNode<T1> find(int key)
{
BNode<T1> current = root;
while (current.key != key)
{
if (current.key < key){
current = current.leftchild;
}
else
{
current = current.rightchild;
}
if(current == null)
{
return null;
}
}
return current;
}
//遍历
public void traverse(int traverseType,List<T1> A)
{
switch (traverseType)
{
case 0:
ascOrder(root,A);
break;
case 1:
centreOrder(root,A);
break;
case 2:
descOrder(root,A);
break;
default:
descOrder(root,A);
break;
}
}
private void ascOrder(BNode<T1> localroot,List<T1> A)
{
if (localroot != null)
{
ascOrder(localroot.leftchild,A);
//输出或存储
A.Add(localroot.data);
ascOrder(localroot.rightchild,A);
}
}
private void descOrder(BNode<T1> localroot, List<T1> A)
{
if(localroot != null)
{
descOrder(localroot.rightchild,A);
//输出或存储
A.Add(localroot.data);
descOrder(localroot.leftchild,A);
}
}
private void centreOrder(BNode<T1> localroot, List<T1> A) {
if (localroot != null)
{
//输出或存储
A.Add(localroot.data);
centreOrder(localroot.leftchild,A);
centreOrder(localroot.rightchild,A);
}
}
//插入
public void insert(int key, T1 value)
{
BNode<T1> newnode = new BNode<T1>();
newnode.key = key;
newnode.data = value;
if (root == null)
{
root = newnode;
}
else
{
BNode<T1> current = root;
BNode<T1> parent;
while (true)
{
parent = current;
if (newnode.key < current.key)
{
current = current.leftchild;
if (current == null)
{
parent.leftchild = newnode;
newnode.parent = parent;
return;
}
}
else
{
current = current.rightchild;
if (current == null)
{
parent.rightchild = newnode;
newnode.parent = parent;
return;
}
}
}
}
}
//删除,考虑根节点情况,没有Child直接删,有一个直接连起来,有两个先找后续节点(右子节点的最后一个左子节点),处理后续问题
public bool delete(int key)
{
BNode<T1> current = root;
bool isLeftChild = true;
if(current == null)
{
return false;
}
while (current.key != key)
{
if (key < current.key)
{
isLeftChild = true;
current = current.leftchild;
}
else
{
isLeftChild = false;
current = current.rightchild;
}
if (current == null)
{
return false;
}
}
if (current.leftchild == null && current.rightchild == null)
{
return deleteNoChild(current, isLeftChild);
}
else if (current.leftchild != null && current.rightchild != null)
{
return deleteTwoChild(current, isLeftChild);
}
else
{
return deleteOneChild(current, isLeftChild);
}
}
private bool deleteNoChild(BNode<T1> node, bool isLeftChild)
{
if (node == root)
{
root = null;
return true;
}
if (isLeftChild)
{
node.parent.leftchild = null;
}
else
{
node.parent.rightchild = null;
}
return true;
}
private bool deleteOneChild(BNode<T1> node,bool isLeftChild)
{
if (node.leftchild == null)
{
if (node == root)
{
root = node.rightchild;
node.parent = null;
return true;
}
if(isLeftChild)
{
node.parent.leftchild = node.rightchild;
}
else
{
node.parent.rightchild = node.rightchild;
}
node.rightchild.parent = node.parent;
}
else
{
if (node == root)
{
root = node.leftchild;
node.parent = null;
return true;
}
if (isLeftChild)
{
node.parent.leftchild = node.leftchild;
}
else
{
node.parent.rightchild = node.leftchild;
}
node.leftchild.parent = node.parent;
}
return true;
}
private bool deleteTwoChild(BNode<T1> node,bool isLeftChild)
{
BNode<T1> successor = getSuccessor(node);
if (node == root)
{
successor.leftchild = root.leftchild;
successor.rightchild = root.rightchild;
successor.parent = null;
root = successor;
}
else if(isLeftChild){
node.parent.leftchild = successor;
}
else
{
node.parent.rightchild = successor;
}
successor.leftchild = node.leftchild;
return true;
}
private BNode<T1> getSuccessor(BNode<T1> delNode)
{
BNode<T1> successor = delNode;
BNode<T1> current = delNode.rightchild;
while (current != null)
{
successor = current;
current = current.leftchild;
}
if (successor != delNode.rightchild)
{//对拿走后续节点的空缺进行处理
successor.parent.leftchild = successor.rightchild;
if (successor.rightchild != null)
{
successor.rightchild.parent = successor.parent;
}
//将后续节点与右边连上
successor.rightchild = delNode.rightchild;
}
return successor;
}
//销毁
public void clear()
{
destroy(root);
root = null;
}
public void destroy(BNode<T1> localtree)
{
if (localtree == null)
{
return;
}
if (localtree.leftchild != null)
{
destroy(localtree.leftchild);
}
if (localtree.rightchild != null)
{
destroy(localtree.rightchild);
}
localtree = null;
}
}
public class BNode<T1>
{
public int key;
public T1 data;
public BNode<T1> parent;
public BNode<T1> leftchild;
public BNode<T1> rightchild;
}
//-----------------------------------------------------------
public class RBTree<T1>
{
private RBNode<T1> root;//根
public RBTree()
{
root = null;
}
//查询
public RBNode<T1> maxNode()
{
RBNode<T1> current = root;
RBNode<T1> parent = root;
while (current != null)
{
parent = current;
current = current.rightchild;
}
return parent;
}
public RBNode<T1> minNode()
{
RBNode<T1> current = root;
RBNode<T1> parent = root;
while (current != null)
{
parent = current;
current = current.leftchild;
}
return parent;
}
public RBNode<T1> find(int key)
{
RBNode<T1> current = root;
while (current.key != key)
{
if (current.key < key)
{
current = current.leftchild;
}
else
{
current = current.rightchild;
}
if (current == null)
{
return null;
}
}
return current;
}
//遍历
public void traverse(int traverseType, List<T1> A)
{
switch (traverseType)
{
case 0:
ascOrder(root, A);
break;
case 1:
centreOrder(root, A);
break;
case 2:
descOrder(root, A);
break;
default:
descOrder(root, A);
break;
}
}
private void ascOrder(RBNode<T1> localroot, List<T1> A)
{
if (localroot != null)
{
ascOrder(localroot.leftchild, A);
//输出或存储
A.Add(localroot.data);
ascOrder(localroot.rightchild, A);
}
}
private void descOrder(RBNode<T1> localroot, List<T1> A)
{
if (localroot != null)
{
descOrder(localroot.rightchild, A);
//输出或存储
A.Add(localroot.data);
descOrder(localroot.leftchild, A);
}
}
private void centreOrder(RBNode<T1> localroot, List<T1> A)
{
if (localroot != null)
{
//输出或存储
A.Add(localroot.data);
centreOrder(localroot.leftchild, A);
centreOrder(localroot.rightchild, A);
}
}
//插入
private void leftRotate(RBNode<T1> node)
{
RBNode<T1> rnode = node.rightchild;
node.rightchild = rnode.leftchild;
if (rnode.leftchild != null) rnode.leftchild.parent = node;
rnode.parent = node.parent;
if (rnode.parent == null)
{
root = rnode;
}
else
{
if (node == node.parent.leftchild)
{
node.parent.leftchild = rnode;
}
else
{
node.parent.rightchild = rnode;
}
}
rnode.leftchild = node;
node.parent = rnode;
}
private void rightRotate(RBNode<T1> node)
{
RBNode<T1> lnode = node.leftchild;
node.leftchild = lnode.rightchild;
if (lnode.rightchild != null)
{
lnode.rightchild.parent = node;
}
lnode.parent = node.parent;
if (node.parent == null)
{
root = lnode;
}
else
{
if (node == node.parent.leftchild)
{
node.parent.leftchild = lnode;
}
else
{
node.parent.rightchild = lnode;
}
}
node.parent = lnode;
lnode.rightchild = node;
}
private void insertFix(RBNode<T1> node)
{
RBNode<T1> parent, gparent;
parent = node.parent;
//1.插入节点的父节点和其叔叔节点(祖父节点的另一个子节点)均为红色的
//2.插入节点的父节点是红色,叔叔节点是黑色,且插入节点是其父节点的右子节点
//3.插入节点的父节点是红色,叔叔节点是黑色,且插入节点是其父节点的左子节点。
while (parent != null && !parent.color)
{//当父节点是红色时
gparent = parent.parent;
if (parent == gparent.leftchild)
{//父节点为左子节点
RBNode<T1> uncle = gparent.rightchild;
if (uncle != null && !uncle.color)
{//叔叔节点也是红色
uncle.color = true;
parent.color = true;
gparent.color = false;
node = gparent;
continue;//继续向上判断
}
if (node == parent.rightchild)
{//叔叔是黑色,当前为右子节点
leftRotate(parent);
RBNode<T1> tmp = parent;//调整旋转后的当前节点
parent = node;
node = tmp;
}
//叔叔为黑色,当前左子节点
parent.color = true;
gparent.color = false;
rightRotate(gparent);
}
else
{//父节点为右子节点,同上
RBNode<T1> uncle = gparent.leftchild;
if (uncle != null & !uncle.color)
{
uncle.color = true;
parent.color = true;
gparent.color = false;
node = gparent;
continue;
}
if (node == parent.leftchild)
{
rightRotate(parent);
RBNode<T1> tmp = parent;
parent = node;
node = tmp;
}
parent.color = true;
gparent.color = false;
leftRotate(gparent);
}
}
root.color = true;
}
public void insert(int key,T1 value)
{
RBNode<T1> current = root;
RBNode<T1> node = new RBNode<T1>(key,false,value);
if (root == null)
{
node.color = true;
root = node;
return;
}
RBNode<T1> parent;
while (current != null)
{
parent = current;
if (node.key < current.key)
{
current = current.leftchild;
if (current == null)
{
parent.leftchild = node;
node.parent = parent;
insertFix(node);
return;
}
}
else
{
current = current.rightchild;
if (current == null)
{
parent.rightchild = node;
node.parent = parent;
insertFix(node);
return;
}
}
}
}
//删除
public bool remove(int key)
{
RBNode<T1> node;
node = find(key);
if (node == null)
{
return false;
}
RBNode<T1> child, parent;
bool color;
if(node.leftchild == null && node.rightchild == null)
{//没有子节点
if (node == root)
{
root = null;
return true;
}
if (node.parent.leftchild==node)
{
node.parent.leftchild = null;
}
else
{
node.parent.rightchild = null;
}
return true;
}
if ((node.leftchild != null) && (node.rightchild != null))
{//有两个子节点
//1.获取后续节点
RBNode<T1> replace = node;
replace = replace.rightchild;
while (replace.leftchild != null)
{
replace = replace.leftchild;
}
//2.连接父节点与后继节点
if (node.parent != null)
{
if (node == node.parent.leftchild)
{
node.parent.leftchild = replace;
}
else
{
node.parent.rightchild = replace;
}
}
else
{//如果是根节点
root = replace;
}
//3.处理关系问题
child = replace.rightchild;
parent = replace.parent;
color = replace.color;
if (parent == node)
{//后继是被删除节点的子节点
parent = replace;
}
else
{
if (child != null)
{
child.parent = parent;
}
parent.leftchild = child;
replace.rightchild = node.rightchild;
node.rightchild.parent = replace;
}
replace.parent = node.parent;
replace.color = node.color;
replace.leftchild = node.leftchild;
node.leftchild.parent = replace;
//4.后续节点是黑色,那么需要修正红黑树
if (color == true)
{
removeFix(child, parent);
}
node = null;
return true;
}
else
{
if (node.leftchild == null)
{
if (node == root)
{
root = node.rightchild;
node.parent = null;
return true;
}
if (node.parent.leftchild==node)
{
node.parent.leftchild = node.rightchild;
}
else
{
node.parent.rightchild = node.rightchild;
}
node.rightchild.parent = node.parent;
if (node.color == true)
{
removeFix(node.rightchild,node.rightchild.parent);
}
node = null;
}
else
{
if (node == root)
{
root = node.leftchild;
node.parent = null;
return true;
}
if (node.parent.leftchild==node)
{
node.parent.leftchild = node.leftchild;
}
else
{
node.parent.rightchild = node.leftchild;
}
node.leftchild.parent = node.parent;
if (node.color == true)
{
removeFix(node.leftchild, node.leftchild.parent);
}
node = null;
}
return true;
}
}
private void removeFix(RBNode<T1> node,RBNode<T1> parent)
{
RBNode<T1> other;
while ((node == null || node.color) && node != root)
{
if (parent.leftchild == node)
{//一、node是左子节点
other = parent.rightchild;
if (!other.color)
{//1.node的兄弟节点other是红色
other.color = true;
parent.color = false;
leftRotate(parent);
other = parent.rightchild;
}
if ((other.leftchild == null || other.leftchild.color) && (other.rightchild == null || other.rightchild.color))
{//2.node的兄弟节点other是黑色的,且other的两个子节点也是黑色的
other.color = false;
node = parent;
parent = node.parent;
}
else
{//3.node的兄弟节点other是黑色的,且other的左子节点是红色,右子节点是黑色
if (other.rightchild == null || other.rightchild.color)
{
other.leftchild.color = true;
other.color = false;
rightRotate(other);
other = parent.rightchild;
}
//4.node的有兄弟节点是黑色,且other的右子节点是红色,左子节点任意颜色
other.color = parent.color;
parent.color = true;
other.rightchild.color = true;
leftRotate(parent);
node = this.root;
break;
}
}
else
{
other=parent.leftchild;
if (!other.color)
{
other.color = true;
parent.color = false;
rightRotate(parent);
other = parent.leftchild;
}
if ((other.leftchild == null || other.leftchild.color) && (other.rightchild == null || other.rightchild.color))
{
other.color = false;
node = parent;
parent = node.parent;
}
else
{
if (other.leftchild == null || other.leftchild.color)
{
other.rightchild.color = true;
other.color = false;
leftRotate(other);
other = parent.leftchild;
}
other.color = parent.color;
parent.color = true;
other.leftchild.color = true;
rightRotate(parent);
node = root;
break;
}
}
}
if (node != null)
{
node.color = true;
}
}
//销毁
public void clear()
{
destroy(root);
root = null;
}
public void destroy(RBNode<T1> localtree)
{
if (localtree == null)
{
return;
}
if (localtree.leftchild != null)
{
destroy(localtree.leftchild);
}
if (localtree.rightchild != null)
{
destroy(localtree.rightchild);
}
localtree = null;
}
}
public class RBNode<T1>
{
public int key;
public bool color;
public T1 data;
public RBNode<T1> parent;
public RBNode<T1> leftchild;
public RBNode<T1> rightchild;
public RBNode(int _key,bool _color,T1 _data)
{
this.key = _key;
this.color = _color;
this.data = _data;
}
}
}