红黑树刨析与应用

红黑树刨析与应用

介绍

红黑树(平衡二叉搜索树)是2-3节点树的一种实现方式
2-3节点树(又称 3阶B树) 是一种完美平衡的树

以 35、75、65、56、78、29、41、37、38 为例

体验中心

https://www.cs.usfca.edu/~galles/visualization/BTree.html

在这里插入图片描述

将2-3结点树中的 2-结点 用红色指针连接便转化成了红黑树

在这里插入图片描述
在这里插入图片描述

红圆圈代表:它与父节点的连接为红连接

此图为自顶向下的红黑树,如果自下向上可以将35,65转成黑连接,在将根连接转成黑色,且38,78结点可以进行左旋转

红黑树的等价定义

红连接均为左连接
• 没有任何一个结点同时和两条红色连接相连
• 该树为完美黑色平衡树,即任意空连接到根节点的路径上的黑连接数量相同

结点结构(Node)

private static final boolean RED=true;
private static final boolean BLACK=false;
private class Node{
    Key key; //健
    Value value; //值
    Node left,right; //左右子树
    int N; //这颗子树的结点总数
    boolean color //结点颜色 RED:true   BLACK:false;
        
}
//工具类
//左旋转
Node rorateLeft(Node h){
    Node x=h.right;
    h.right=x.left;
    x.color=h.color;
    h.color=RED;
    X.N=h.N;
    h.N=1+h.left.N+h.right.N;
    return x;  //返回值为旋转后父节点的地址即第二张图中的x;
}

(注意看 S,E的位置,粗实线代表红结点,也代表E,S是一个2结点)
在这里插入图片描述

										|  |
										 \ /

在这里插入图片描述

//右选择
Node rorateRight(Node h){
    Node.x=h.left;
    h.left=x.right;
    x.right=h;
    x.color=h.color;
    h.color=RED;
    x.N=h.N;
    h.N=1+h.left.N+h.right.N;
    return x;//返回值为旋转后父节点的地址即第二张图中的x;
}
         

在这里插入图片描述

                   				 	   |  |
							        	 \/

在这里插入图片描述

旋转的作用

为了满足(不存在两条连续的红连接和不存在红色的右连接)的条件

插入新结点

插入时,要将新结点的链接标注为红链接   (思考2-3结点树的插入动作就知道为什么要这样做了)

①当插入新结点时,将 单个结点转化成2-结点
• 1.当插入的左边时(不用进行任何操作)
在这里插入图片描述

• 2.当插入的右边时(进行左旋转)
在这里插入图片描述

②当插入新结点时,将 2-结点转化成3-结点
Ⅰ.当插入节点变成下图时(直接将两个红链接变成黑链接并父结点的链接变成红链接即可,红黑树就是以这种方式减少红链接数的)
在这里插入图片描述


• Ⅱ.当插入节点变成下图时(先进行右旋转在进行Ⅰ操作)
在这里插入图片描述

• Ⅲ.当插入节点变成下图时(先进行左旋转在进行Ⅱ操作)
在这里插入图片描述

put方法的实现

private isRed(Node node){
    if(x==null) return false;
    return x.color==RED;
}.Ⅰ的情况
private  flipColors(Node h){
    h.color=RED;
    h.left.color=BLACK;
    h.right.color=RED;
}
private Node put(Node h,Key key ,Value val){
    if(h==null)  return New Node(key,val,1,RED); //当走到叶子结点时,创建新结点
    
    int cmp=key.compare(h.key)  //如果 key>h.key 返回 1;  key=h.key :0   key<h.key -1
        
    if(cmp<0) h.left=put(h.left,key,val); //走左子树
    else if(cmp>0) h.right=put(h.right,key,val); //走右子树
    else h.val=val //有等值的Key就进行替换value即可
       if(isRed(h.right)&&!isRed(h.left)) h=rotateLeft(h) ;// ①.2的情况
       if(isRed(h.left)&&isRed(h.left.left))  h=rotateRight(h); //②.Ⅱ的情况
       if(isRed(h.left)&&isRed(h.right)) flipColors(h);// ②.Ⅰ的情况   
           h.N=1+h.left.N+h.right.N;
    return h;
}

get方法的实现

private Node get(Node h,Key key){
        if(h==null)   return null
   int cmp=key.compare(h.key) 
     if(cmp<0)  return  get(h.left,key);
     else if(cmp>0) return get(h.right,key);
     else  return h.val;
    }

红黑树的应用

  • JDK1.8之后的Hashmap类中当一个桶中Hash碰撞大于8次时,会将链表转化成红黑树,来提高效率
  • TreeMap,TreeSet也是用红黑树实现的

HashMap的实现

**

应用的数据结构:数组+链表+红黑树 初始桶数(capctity)为16-----数组实现
负载因子为0.75(loadFactor=size/capctity) ----size:
key-value键值对的数量,当loadFactor>0.75时capctity会进行扩容(扩容的倍数为2的次方)

**

 	//capctity
    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
    //loadfactor
     static final float DEFAULT_LOAD_FACTOR = 0.75f;

关于HashMap的hash实现

static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    //将32位的int 分为高16位和低16位进行异或,得到高低16位共同作用的hash值
    这么做可以在数组table的length比较小的时候,也能保证高低Bit都参与到Hash的计算中
}
 i=(table.length-1)&hash;//进行取模,通过hash确认次key在哪个桶中
    //(table.length-1)&hash 等价于 hash%table.length

红黑树,B树,B+树的区别

① 红黑树一个Node只有一个key-value键值对,B树和B+一个Node会有多个Key-value键值对 ②B树的叶子结点不会用链表,B+树的所有key-value键值对都会在叶子结点且用链表链接 这也是为什么
Mysql中的innodb存储引擎有B+树来实现,因为顺序查找更快

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值