加入收藏 | 设为首页 | 会员中心 | 我要投稿 常州站长网 (https://www.0519zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 运营中心 > 建站资源 > 优化 > 正文

3分钟让你明白:HashMap之红黑树树化过程

发布时间:2019-10-13 11:07:40 所属栏目:优化 来源:追逐仰望星空
导读:副标题#e# 01 概述 HashMap是Java程序员使用频率最高的用于映射(键值对)处理的数据类型。随着JDK(Java Developmet Kit)版本的更新,JDK1.8对HashMap底层的实现进行了优化,例如引入红黑树的数据结构和扩容的优化等。本文主要分析一下HashMap中红黑树树化的

我们看balanceInsertion

  1. static <K, V> TreeNode<K, V> balanceInsertion(TreeNode<K, V> root, TreeNode<K, V> x) 
  2.  { 
  3.  // 正如开头所说,新加入树节点默认都是红色的,不会破坏树的结构。 
  4.  x.red = true; 
  5.  // 这些变量名不是作者随便定义的都是有意义的。 
  6.  // xp:x parent,代表x的父节点。 
  7.  // xpp:x parent parent,代表x的祖父节点 
  8.  // xppl:x parent parent left,代表x的祖父的左节点。 
  9.  // xppr:x parent parent right,代表x的祖父的右节点。 
  10.  for (TreeNode<K, V> xp, xpp, xppl, xppr;;) 
  11.  { 
  12.  // 如果x的父节点为null说明只有一个节点,该节点为根节点,根节点为黑色,red = false。 
  13.  if ((xp = x.parent) == null) 
  14.  { 
  15.  x.red = false; 
  16.  return x; 
  17.  }  
  18.  // 进入else说明不是根节点。 
  19.  // 如果父节点是黑色,那么大吉大利(今晚吃鸡),红色的x节点可以直接添加到黑色节点后面,返回根就行了不需要任何多余的操作。 
  20.  // 如果父节点是红色的,但祖父节点为空的话也可以直接返回根此时父节点就是根节点,因为根必须是黑色的,添加在后面没有任何问题。 
  21.  else if (!xp.red || (xpp = xp.parent) == null) 
  22.  return root; 
  23.   
  24.  // 一旦我们进入到这里就说明了两件是情 
  25.  // 1.x的父节点xp是红色的,这样就遇到两个红色节点相连的问题,所以必须经过旋转变换。 
  26.  // 2.x的祖父节点xpp不为空。 
  27.   
  28.  // 判断如果父节点是否是祖父节点的左节点 
  29.  if (xp == (xppl = xpp.left)) 
  30.  { 
  31.  // 父节点xp是祖父的左节点xppr 
  32.  // 判断祖父节点的右节点不为空并且是否是红色的 
  33.  // 此时xpp的左右节点都是红的,所以直接进行上面所说的第三种变换,将两个子节点变成黑色,将xpp变成红色,然后将红色节点x顺利的添加到了xp的后面。 
  34.  // 这里大家有疑问为什么将x = xpp? 
  35.  // 这是由于将xpp变成红色以后可能与xpp的父节点发生两个相连红色节点的冲突,这就又构成了第二种旋转变换,所以必须从底向上的进行变换,直到根。 
  36.  // 所以令x = xpp,然后进行下下一层循环,接着往上走。 
  37.  if ((xppr = xpp.right) != null && xppr.red) 
  38.  { 
  39.  xppr.red = false; 
  40.  xp.red = false; 
  41.  xpp.red = true; 
  42.  x = xpp; 
  43.  } 
  44.  // 进入到这个else里面说明。 
  45.  // 父节点xp是祖父的左节点xppr。 
  46.  // 祖父节点xpp的右节点xppr是黑色节点或者为空,默认规定空节点也是黑色的。 
  47.  // 下面要判断x是xp的左节点还是右节点。 
  48.  else 
  49.  { 
  50.  // x是xp的右节点,此时的结构是:xpp左->xp右->x。这明显是第二中变换需要进行两次旋转,这里先进行一次旋转。 
  51.  // 下面是第一次旋转。 
  52.  if (x == xp.right) 
  53.  { 
  54.  root = rotateLeft(root, x = xp); 
  55.  xpp = (xp = x.parent) == null ? null : xp.parent; 
  56.  } 
  57.  // 针对本身就是xpp左->xp左->x的结构或者由于上面的旋转造成的这种结构进行一次旋转。 
  58.  if (xp != null) 
  59.  { 
  60.  xp.red = false; 
  61.  if (xpp != null) 
  62.  { 
  63.  xpp.red = true; 
  64.  root = rotateRight(root, xpp); 
  65.  } 
  66.  } 
  67.  } 
  68.  }  
  69.  // 这里的分析方式和前面的相对称只不过全部在右测不再重复分析。 
  70.  else 
  71.  { 
  72.  if (xppl != null && xppl.red) 
  73.  { 
  74.  xppl.red = false; 
  75.  xp.red = false; 
  76.  xpp.red = true; 
  77.  x = xpp; 
  78.  } else 
  79.  { 
  80.  if (x == xp.left) 
  81.  { 
  82.  root = rotateRight(root, x = xp); 
  83.  xpp = (xp = x.parent) == null ? null : xp.parent; 
  84.  } 
  85.  if (xp != null) 
  86.  { 
  87.  xp.red = false; 
  88.  if (xpp != null) 
  89.  { 
  90.  xpp.red = true; 
  91.  root = rotateLeft(root, xpp); 
  92.  } 
  93.  } 
  94.  } 
  95.  } 
  96.  } 
  97.  } 

如果您的联想能力很强的话估计到这里应该已经理解这集中变换的主要的关系。

下面简述一下前面的两种种幸运的情况

(编辑:常州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读