TreeMap 的底层原理

TreeMap 的底层原理详解

一、数据结构

TreeMap 是基于 红黑树(Red-Black Tree) 实现的有序映射(SortedMap),其核心特性为 按键的自然顺序或自定义比较器排序。以下是其核心结构:

  1. 红黑树特性
    平衡规则
    ◦ 每个节点为红色或黑色。
    ◦ 根节点和叶子节点(NIL)必须为黑色。
    ◦ 红色节点的子节点必须为黑色(即不能有连续红色节点)。
    ◦ 从任一节点到其所有叶子节点的路径包含相同数量的黑色节点(黑高相同)。
    平衡效果:红黑树通过上述规则确保树的高度近似为 O(log n),从而保证操作的高效性。

  2. 节点结构(Entry)

    static final class Entry<K,V> implements Map.Entry<K,V> {
        K key;
        V value;
        Entry<K,V> left;    // 左子节点
        Entry<K,V> right;   // 右子节点
        Entry<K,V> parent;  // 父节点
        boolean color = BLACK; // 节点颜色(默认黑色)
    }
    

二、核心操作原理
1. 插入(put)

步骤
a. 二叉查找树插入:根据键的顺序找到插入位置,创建新节点(初始颜色为红色)。
b. 平衡修复(fixAfterInsertion):通过旋转和颜色调整修复红黑树性质。

修复逻辑
情况 1:插入节点的父节点是黑色。
◦ 无需调整,直接插入。
情况 2:插入节点的父节点是红色。
Case 2a:叔节点(父节点的兄弟节点)为红色。
将父节点和叔节点变为黑色,祖父节点变为红色,递归处理祖父节点。
Case 2b:叔节点为黑色或不存在,且插入节点与父节点的方向不一致(如父节点是左子,插入节点是右子)。
对父节点左旋或右旋,转化为 Case 2c。
Case 2c:叔节点为黑色或不存在,且插入节点与父节点的方向一致。
将父节点变为黑色,祖父节点变为红色,对祖父节点进行旋转。

2. 删除(remove)

步骤
a. 二叉查找树删除:找到待删除节点,用其后继节点(右子树的最小节点)替代。
b. 平衡修复(fixAfterDeletion):根据替代节点的颜色调整树结构。

修复逻辑
• 若替代节点为红色,直接删除,无需调整。
• 若替代节点为黑色,需从删除位置向上递归修复黑高平衡。
Case 1:兄弟节点为红色。
将兄弟节点变为黑色,父节点变为红色,对父节点旋转,转化为其他情况。
Case 2:兄弟节点为黑色,且其子节点均为黑色。
将兄弟节点变为红色,递归处理父节点。
Case 3:兄弟节点为黑色,且远侄子节点(兄弟节点的右子节点)为红色。
交换父节点与兄弟节点颜色,将远侄子节点变为黑色,对父节点旋转。
Case 4:兄弟节点为黑色,且近侄子节点(兄弟节点的左子节点)为红色。
将兄弟节点变为红色,近侄子节点变为黑色,对兄弟节点旋转,转化为 Case 3。

3. 查询(get)

原理:基于二叉查找树的搜索逻辑,时间复杂度为 O(log n)

final Entry<K,V> getEntry(Object key) {
    Entry<K,V> p = root;
    while (p != null) {
        int cmp = comparator.compare(key, p.key);
        if (cmp < 0) p = p.left;
        else if (cmp > 0) p = p.right;
        else return p;
    }
    return null;
}

三、有序性实现
  1. 中序遍历
    TreeMap 的键值对按 左子树 → 根节点 → 右子树 的顺序遍历,保证升序排列。
    EntrySet 迭代器

    Iterator<Map.Entry<K,V>> it = treeMap.entrySet().iterator();
    while (it.hasNext()) {
        Map.Entry<K,V> entry = it.next();
        // 按顺序访问键值对
    }
    
  2. 范围查询
    支持 subMap()headMap()tailMap() 等方法,利用红黑树的有序特性快速定位范围。


四、性能分析
操作时间复杂度说明
插入(put)O(log n)需平衡修复,但红黑树高度为对数级
删除(remove)O(log n)同插入,需处理最坏情况的平衡调整
查询(get)O(log n)类似二分查找
遍历(forEach)O(n)中序遍历所有节点

五、与 HashMap 的对比
特性TreeMapHashMap
数据结构红黑树数组 + 链表/红黑树
顺序性按键有序无序
时间复杂度(增删查)O(log n)O(1)(理想情况下)
内存占用较高(存储父节点和颜色)较低
适用场景需排序或范围查询快速随机访问

六、线程安全与扩展
  1. 线程不安全
    TreeMap 未内置同步机制,多线程环境下需通过外部同步或使用 Collections.synchronizedSortedMap() 包装。

    SortedMap<K,V> syncTreeMap = Collections.synchronizedSortedMap(new TreeMap<>());
    
  2. 并发替代方案
    在并发场景下,可选用 ConcurrentSkipListMap,基于跳表(Skip List)实现,提供类似的有序性和线程安全。


七、典型应用场景
  1. 需要按键排序的映射,如字典序、数值排序等。
  2. 范围查询操作,例如统计某个区间内的键值对。
  3. 实现有序缓存,结合 LRU 策略的变种(需自定义比较器)。

总结

TreeMap 的核心原理基于 红黑树,通过颜色和旋转规则维持树的平衡,保证操作的高效性(O(log n))。其优势在于:
有序性:支持自然排序或自定义排序。
范围操作:高效实现子映射查询。
稳定性:在动态数据场景下性能优于普通二叉查找树。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值