TreeNode既是红黑树节点又是链表节点,因其继承LinkedHashMap.Entry(含before/after)且源自Node(含prev/next),分别支持树结构(left/right/parent/red)和哈希桶内链表连接(prev/next)。
TreeNode为什么既是红黑树节点又是链表节点
因为
继承自
,而后者本身就有
和
字段——这是双向链表的前驱/后继指针。所以它天然支持两种结构:作为红黑树节点时用
/
/
/
;作为插入顺序链表节点时用
/
(注意:不是
/
,
/
来自
的继承,用于哈希桶内链表连接)。
常见错误现象:
出现在遍历
的
或
时,其实是误把树节点当普通链表节点直接遍历,忽略了它只在「树化后仍需维持原桶内顺序」时才有效连接。
和
仅在该
被挂载到哈希桶数组中时被维护(比如调用
后),不是树结构的一部分
树内遍历必须走
/
,不能靠
遍历整棵树
反树化(
)时会用
/
快速重建链表,但此时
/
已失效
treeify() 怎么把链表转成红黑树
核心是两步:先构造一棵普通的二叉搜索树(BST),再通过
逐个染色+旋转,恢复红黑性质。整个过程不改变原有
的
/
/
,只是把它们包装成
并重连指针。
使用场景:当某个桶中
链表长度 ≥ 8 且哈希表容量 ≥ 64 时触发,否则只扩容不树化。
树化前会尝试用
+
获取 key 的自然序;失败则 fallback 到
(基于
和类名哈希)保证可比性
所有新创建的
默认为红色,插入后统一由
调整
注意:树化不是“复制数据”,而是原地升级节点类型——原来的
对象被强转为
,其
字段仍保留,用于维持桶内链表结构
removeTreeNode() 删除时最常踩的三个坑
删除操作远比插入复杂,因为要同时维护红黑树平衡和哈希桶链表结构,稍有不慎就断链或失衡。
X-Node企业快速建站1.0.6.0801
特色介绍: 1、ASP+XML+XSLT开发,代码、界面、样式全分离,可快速开发 2、支持语言包,支持多模板,ASP文件中无任何HTML or 中文 3、无限级分类,无限级菜单,自由排序 4、自定义版头(用于不规则页面) 5、自动查找无用的上传文件与空目录,并有回收站,可删除、还原、永久删除 6、增强的Cache管理,可单独管理单个Cache 7、以内存和XML做为Cache,兼顾性能与消耗 8、
下载
常见错误现象:删除后
返回 null、
不对、甚至
(多线程下未同步)。
没调用
或漏掉
重连逻辑,导致该桶的
指向一个已从树中摘除但未从桶链表中移出的节点
删除后未调用
,红黑树黑高失衡,后续查找可能漏节点(尤其在左/右子树黑高不等时)
反树化阈值判断写错:JDK 规定树中节点 ≤ 6 才
,但有人误用“桶中总节点数 ≤ 6”,忽略当前已是树结构的事实
TreeNode 的 color 字段为什么是布尔型而不是枚举
因为
字段定义为
,不是
。这是纯粹的性能取舍:避免对象创建和虚方法分派,用单 bit 存储更省内存、更快访问。
性能影响:在高频插入/删除路径(如
、
)中,每次颜色判断都是
这种直接位读取,比
少一次字段解引用和常量比较。
所有红黑树操作(
、
、
)都基于这个布尔值做分支,没有抽象层
别试图给
加 color getter/setter——它压根没提供,直接读写
字段是唯一正解
调试时打印
看不到 color?那是
没输出它,得手动打
真正麻烦的从来不是“怎么写 TreeNode”,而是搞清它在哪一刻属于树、在哪一刻属于链表、又在哪一刻两者都得保——这三个身份切换全靠几行指针赋值,手抖一下,
指向了
,或者
没挪到桶头,问题就藏进去了。
TreeNodeLinkedHashMap.EntrybeforeafterleftrightparentredprevnextbeforeafterprevnextNodeNullPointerExceptionTreeNodeprevnextprevnextTreeNodemoveRootToFrontleftrightnextuntreeifyprevnextleftrightbalanceInsertionNodehashkeyvalueTreeNodeNodecomparableClassForcompareComparablestieBreakOrderSystem.identityHashCodeTreeNodebalanceInsertionNodeTreeNodenextget()size()ConcurrentModificationExceptionunmaproottab[index]balanceDeletionuntreeifyredboolean redColor.RED/BLACKputValremoveNodeif (p.red)if (p.color == Color.RED)rotateLeftrotateRightbalanceInsertionTreeNoderedTreeNodetoString()p.red ? "RED" : "BLACK"prevrightroot