对于完全随机的数据,普通的二分搜索树就很好用,只是在极端情况下会退化成链表。

对于查询较多的情况,avl树很好用。

红黑树牺牲了平衡性,但是它的统计性能更优(综合增删改查所有的操作)。

红黑树java实现(不完整,没有进行删除节点的操作):

(默认左倾红黑树)

package RedBlackTree;

//从任意一个节点到叶子节点,经过的黑色节点是一样的——红黑树是保持“黑平衡”的二叉树
//因为23树中的每一个节点到叶子节点的深度是相同的
//红黑树在严格意义上不是平衡二叉树,最大高度:2logn 时间复杂度是O(logn)
//存储的数据经常需要增加或者删除时 使用红黑树要优于avl树
public class RBTree<K extends Comparable<K>, V> { private static final boolean RED = true;
private static final boolean BLACK = false; private class Node {
public K key;
public V value;
public Node left, right;
//表示颜色
public boolean color; public Node(K key, V value) {
this.key = key;
this.value = value;
left = null;
right = null;
//add时新添加的节点总是要进行融合,所以节点默认为红色
color = RED;
}
} private Node root;
private int size; public RBTree() {
root = null;
size = 0;
} public int getSize() {
return size;
} public boolean isEmpty() {
return size == 0;
} // 判断节点node的颜色
private boolean isRed(Node node){
if(node == null)
return BLACK;
return node.color;
} // node x
// / \ 左旋转 / \
// T1 x ---------> node T3
// / \ / \
// T2 T3 T1 T2
private Node leftRotate(Node node){ Node x = node.right; // 左旋转
node.right = x.left;
x.left = node; x.color = node.color;
node.color = RED; return x;
} // node x
// / \ 右旋转 / \
// x T2 -------> y node
// / \ / \
// y T1 T1 T2
private Node rightRotate(Node node){ Node x = node.left; // 右旋转
node.left = x.right;
x.right = node; x.color = node.color;
node.color = RED; return x;
} // 颜色翻转
private void flipColors(Node node){ node.color = RED;
node.left.color = BLACK;
node.right.color = BLACK;
} // 向红黑树中添加新的元素(key, value)
public void add(K key, V value){
root = add(root, key, value);
root.color = BLACK; // 最终根节点为黑色节点
} // 向以node为根的红黑树中插入元素(key, value),递归算法
// 返回插入新节点后红黑树的根
private Node add(Node node, K key, V value){ if(node == null){
size ++;
return new Node(key, value); // 默认插入红色节点
} if(key.compareTo(node.key) < 0)
node.left = add(node.left, key, value);
else if(key.compareTo(node.key) > 0)
node.right = add(node.right, key, value);
else // key.compareTo(node.key) == 0
node.value = value; if (isRed(node.right) && !isRed(node.left))
node = leftRotate(node); if (isRed(node.left) && isRed(node.left.left))
node = rightRotate(node); if (isRed(node.left) && isRed(node.right))
flipColors(node); return node;
} // 返回以node为根节点的二分搜索树中,key所在的节点
private Node getNode(Node node, K key){ if(node == null)
return null; if(key.equals(node.key))
return node;
else if(key.compareTo(node.key) < 0)
return getNode(node.left, key);
else // if(key.compareTo(node.key) > 0)
return getNode(node.right, key);
} public boolean contains(K key){
return getNode(root, key) != null;
} public V get(K key){ Node node = getNode(root, key);
return node == null ? null : node.value;
} public void set(K key, V newValue){
Node node = getNode(root, key);
if(node == null)
throw new IllegalArgumentException(key + " doesn't exist!"); node.value = newValue;
} // 返回以node为根的二分搜索树的最小值所在的节点
private Node minimum(Node node){
if(node.left == null)
return node;
return minimum(node.left);
} // 删除掉以node为根的二分搜索树中的最小节点
// 返回删除节点后新的二分搜索树的根
private Node removeMin(Node node){ if(node.left == null){
Node rightNode = node.right;
node.right = null;
size --;
return rightNode;
} node.left = removeMin(node.left);
return node;
} // 从二分搜索树中删除键为key的节点
public V remove(K key){ Node node = getNode(root, key);
if(node != null){
root = remove(root, key);
return node.value;
}
return null;
} private Node remove(Node node, K key){ if( node == null )
return null; if( key.compareTo(node.key) < 0 ){
node.left = remove(node.left , key);
return node;
}
else if(key.compareTo(node.key) > 0 ){
node.right = remove(node.right, key);
return node;
}
else{ // key.compareTo(node.key) == 0 // 待删除节点左子树为空的情况
if(node.left == null){
Node rightNode = node.right;
node.right = null;
size --;
return rightNode;
} // 待删除节点右子树为空的情况
if(node.right == null){
Node leftNode = node.left;
node.left = null;
size --;
return leftNode;
} // 待删除节点左右子树均不为空的情况 // 找到比待删除节点大的最小节点, 即待删除节点右子树的最小节点
// 用这个节点顶替待删除节点的位置
Node successor = minimum(node.right);
successor.right = removeMin(node.right);
successor.left = node.left; node.left = node.right = null; return successor;
}
}
}

java——红黑树 RBTree的更多相关文章

  1. 高级搜索树-红黑树(RBTree)解析

    目录 红黑树的定义 节点与树的定义 旋转操作 插入操作 情况1:p的兄弟u为黑色 情况2: p的兄弟u为红色 插入操作性能分析 代码实现 删除操作 情况1:x的接替者succ为红色 情况2:x的接替者 ...

  2. Java红黑树详谈

    定义 红黑树的主要是想对2-3查找树进行编码,尤其是对2-3查找树中的3-nodes节点添加额外的信息.红黑树中将节点之间的链接分为两种不同类型,红色链接,他用来链接两个2-nodes节点来表示一个3 ...

  3. 平衡搜索树--红黑树 RBTree

    红黑树是一棵二叉搜索树,它在每个节点上增加了一个存储位来表示节点的颜色,可以是Red或Black. 通过对任何一条从根到叶子节点简单路径上的颜色来约束树的高度,红黑树保证最长路径不超过最短路径的两倍, ...

  4. 红黑树(RBTREE)之上-------构造红黑树

    该怎么说呢,现在写代码的速度还是很快的,很高兴,o(^▽^)o. 光棍节到了,早上没忍住,手贱了一般,看到*D的优惠,买了个机械键盘,晚上就到了,敲着还是很舒服的,和老婆炫耀了一把哈哈. 光棍节再去* ...

  5. 高级搜索树-红黑树(RBTree)代码实现

    代码实现 代码参考了<数据结构(c++语言版)>--清华大学邓俊辉 "RBTree.h" #pragma once //#include"pch.h" ...

  6. java 红黑树

    背景:总结面试中关于红黑树的相关题目 红黑树(一)之 原理和算法详细介绍 漫画:什么是红黑树? 红黑树是一种自平衡的二叉查找树 红黑树的5个特征:根.叶子都是黑的 节点非红即黑.不能是连续红的.节点到 ...

  7. 红黑树RBTree

    #pragma onceenum colour    //子节点的颜色{    RED,    BLANK,};template<class K,class V>struct RBTree ...

  8. java红黑树

    从这里学了一些知识点https://blog.csdn.net/sun_tttt/article/details/65445754,感谢作者

  9. Java实现红黑树

    转自:http://www.cnblogs.com/skywang12345/p/3624343.html 红黑树的介绍 红黑树(Red-Black Tree,简称R-B Tree),它一种特殊的二叉 ...

随机推荐

  1. Zbar -- 源码分析

    博客转载自:https://blog.csdn.net/sunflower_boy/article/details/50783179 //Img_scanner.c 文件内 int zbar_scan ...

  2. php学习笔记-关联数组

    传统的数组定义方法如下: <?php $names[0]= 'chinese'; $names[1]= 'math'; $names[2]= 'english'; echo $names[2]; ...

  3. 正割、余割、正弦、余弦、正切、余切之间的关系的公式 sec、csc与sin、cos、tan、cot之间的各种公式

    1.倒数关系 tanα ·cotα=1 sinα ·cscα=1 cosα ·secα=1 2.商数关系 tanα=sinα/cosα cotα=cosα/sinα 3.平方关系 sinα²+cosα ...

  4. Git相关安装包打包下载

    Git相关软件偶尔需要***才能下载,故分享于此 1.Git-2.15.0-64-bit.exe 2.TortoiseGit-2.5.0.0-64bit.msi 3.TortoiseGit-Langu ...

  5. easyui textbox 设置只读不可编辑状态

    在使用easyul的时候,发现输入框内容及不容易获取与设置,用jQuery的方式大部分失效.依稀记得好像是因为easyul会在原页面的基础上,生成了一些新的独有样式,并且暂时覆盖掉使用了easyul的 ...

  6. GetResponse() 基础连接已经关闭:服务器关闭了本应保持活动状态的连接

    1.原因: (1)KeepAlive默认为true,与internet保持持续连接 ,服务器关闭了连接,使用HttpWebResponse.GetResponse()出错 (2)HttpWebRequ ...

  7. WebAPI 请求跨域问题

    本人采用的是利用CORS解决跨越问题. 首先利用Nuget 安装“microsoft.aspnet.webapi.cors”,如下图所示: 紧接着,在WebApiConfig文件中加入 config. ...

  8. nodejs nodejs的操作

    nodejs的操作 由于版本造成的命令不能正常安装,请参考五问题 一.概念: 参考百度百科: http://baike.baidu.com/link?url=aUrGlI8Sf20M_YGk8mh-- ...

  9. 移动端自适应个人理解与收集——rem

    rem——更好的适配移动端.这个单位我一直想弄个究竟,今天终于看了个差不多.看了很多的博客.心中总算有自己的想法.(还有vh,vw这里我这个小白还没有弄明白就先不写了.) 1.rem可以在html,b ...

  10. SourceTree——MAC OSX下的Git GUI客户端

    在MAC下面为Git找一款用得顺手的GUI客户端还真不容易.学习工具使用还是先器而后道的路径比较适合我,当年上手CVS SVN都是如此,先通过tortoise客户端熟练了基本操作,之后在搭建构建平台的 ...