java数据结构16_TreeMap底层源码实现(红黑二叉树)

本文深入分析了Java中TreeMap的底层实现,特别是put()和get()方法。首先介绍了TreeMap内部的Entry节点结构,接着详细讲解了put()方法的两个关键步骤:构建排序二叉树和保持红黑树平衡,涉及红黑树的五点规范及不同插入情况下的处理。此外,还探讨了get()方法的实现,包括自然排序和定制排序两种情况。最后指出,TreeMap实际上是以红黑树为基础的数据结构。
摘要由CSDN通过智能技术生成

本章节主要分析红黑树的“插入算法”和“获取算法”,也就是put()方法和get()方法的底层实现。

在学习TreeMap的put()方法之前,我们首先应该创建一个叶子节点Entry类,叶子节点Entry是TreeMap的内部类,它有几个重要的属性:节点的颜色、左子节点指针、右子节点指针、父节点指针、节点的值。

class MyTreeMap<K, V> {
   
// 节点类
	class Entry<K, V> {
   
		// 键
		K key;
		// 值
		V value;
		// 左孩子
		Entry<K, V> left;
		// 右孩子
		Entry<K, V> right;
		// 父亲
		Entry<K, V> parent;
		// 颜色
		boolean color = BLACK;
		// 构造方法
		public Entry(K key, V value, Entry<K, V> parent) {
   
			this.key = key;
			this.value = value;
			this.parent = parent;
		}
	}
}

TreeMap中同时也包含了如下几个重要的属性:

class MyTreeMap<K, V> {
   
	// 比较器,通过comparator接口我们可以对TreeMap的内部排序进行精密的控制
	private final Comparator<? super K> comparator;
	// 红-黑树根节点
	private Entry<K, V> root;
	// 容器大小
	private int size;
	// 红黑树的节点颜色--红色
	private static final boolean RED = false;
	// 红黑树的节点颜色--黑色
	private static final boolean BLACK = true;
    // 此处省略Entry节点类
}

最后,我们再添加两个构造方法,一个无参构造,另外一个有参构造。

class MyTreeMap<K, V> {
   
    // 此处省略MyTreeMap属性
	// 无参构造方法
	public MyTreeMap() {
   
		this.comparator = null; // 默认比较机制
	}
	// 有参构造方法
	public MyTreeMap(Comparator<? super K> comparator) {
   
		this.comparator = comparator; // 自定义比较器的构造方法
	}
    // 此处省略Entry节点类
}

到此处,TreeMap的put()方法的准备工作就已经完成,那么接下来我们就开始分析并实现put()方法。

  • **put()**方法实现

在TreeMap的put()的实现方法中主要分为两个步骤,第一步:构建排序二叉树,第二步:保持红黑树平衡。

  • 第一步:构建排序二叉树

对于排序二叉树的创建,其添加节点的过程如下:

(1) 以根节点为初始节点进行检索。

(2) 与当前节点进行比对,若新增节点值较大,则以当前节点的右子节点作为新的当前节点。否则以当前节点的左子节点作为新的当前节点。

(3) 循环递归2步骤知道检索出合适的叶子节点为止。

(4) 将新增节点与3步骤中找到的节点进行比对,如果新增节点较大,则添加为右子节点;否则添加为左子节点。

按照这个步骤我们就可以将一个新增节点添加到排序二叉树中合适的位置。如下:

class MyTreeMap<K, V> {
   
    // 此处省略MyTreeMap属性和构造方法
    /**
	 * 添加元素
	 * 步骤一:构建排序二叉树 
	 * 步骤二:保持红黑树平衡
	 */
	public V put(K key, V value) {
   
		// 步骤一:构建排序二叉树
		// 1.当红-黑树是空树,把新创建的节点设置为跟节点
		if (null == root) {
    // 当root为null,证明是空树
			// 创建一个Entry节点,并设置为根节点
			root = new Entry<K, V>(key, value, null);
			// 结合元素个数设置为1
			size = 1;
			return null;
		}
		// 2.当红-黑数不为空树,则找到新添加节点的父节点
		// 用t表示二叉树的当前节点
		Entry<K, V> t = root;
		// 用parent表示父节点,并作为新添加节点的父节点
		Entry<K, V> parent;
		// 使用compare表示key排序的返回结果
		int compare;
		// 2.1如果comparator不为null,则采用外部比较器进行创建TreeMap集合
		if (null != comparator) {
   
			do {
   
				// parent指向上次循环后的t
				parent = t;
				// 比较新增节点的key和当前节点key的大小
				compare = comparator.compare(key, t.key);
				// compare返回值小于0,表示新增节点的key小于当前节点的key
				// 则以当前节点的左子节点作为新的当前节点
				if (compare < 0) {
   
					t = t.left;
				}
				// compare返回值大于0,表示新增节点的key大于当前节点的key
				// 则以当前节点的右子节点作为新的当前节点
				else if (compare > 0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值