1:TreeMap是java中排序的Map,实现的原理是基于红黑树。
红黑树原理介绍的blog:
http://www.cnblogs.com/fanzhidongyzby/p/3187912.html
红黑树最难的其实就是:
1:插入的时候, 怎么修正树结构
2:删除的时候,怎么修正树结构
因为出现的类型比较多,判断的也比较多;但是原理都一样,保证高度不超过1,一般都是用旋转达到平衡
测试例子:
public void treeMapTest() { Map<Object, Object> treeMap=new TreeMap<Object, Object>(); treeMap.put(10, 10); treeMap.put(11, 11); treeMap.put(9, 9); treeMap.put(8, 8); Iterator<Object> it=treeMap.keySet().iterator(); while(it.hasNext()) { Object key=it.next(); System.out.println(treeMap.get(key)); } }
TreeMap中保存树结构的类Entry<K,V>
static final class Entry<K,V> implements Map.Entry<K,V> { K key; V value; Entry<K,V> left = null; //左孩子 Entry<K,V> right = null; //右孩子 Entry<K,V> parent; //父亲 boolean color = BLACK; // 默认颜色为黑 /** * Make a new cell with given key, value, and parent, and with * <tt>null</tt> child links, and BLACK color. */ Entry(K key, V value, Entry<K,V> parent) { this.key = key; this.value = value; this.parent = parent; } }
是链表的形式保存所有的节点,在来看看TreeMap的中的属性
public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, Cloneable, java.io.Serializable { /** *比较器,实现这个可以比较大小 */ private final Comparator<? super K> comparator; private transient Entry<K,V> root = null; /** * 树的节点数量 */ private transient int size = 0; }
TreeMap的插入过程,就是红黑树的插入过程,即是:
1:当然key,如果比root节点小,走左孩子,大走右孩子
public V put(K key, V value) { Entry<K,V> t = root; //根节点 if (t == null) { //根节点为空,第一次put root = new Entry<K,V>(key, value, null); size = 1; modCount++; return null; } int cmp; Entry<K,V> parent; Comparator<? super K> cpr = comparator; //是否自定义比较器 if (cpr != null) { do { parent = t; cmp = cpr.compare(key, t.key); if (cmp < 0) t = t.left; else if (cmp > 0) t = t.right; else return t.setValue(value); } while (t != null); } else { //默认的KEY自然排序 if (key == null) throw new NullPointerException(); Comparable<? super K> k = (Comparable<? super K>) key; do { parent = t; // 保存父亲 cmp = k.compareTo(t.key); if (cmp < 0) // 小,走左孩子 t = t.left; else if (cmp > 0) // 大, 走右孩子 t = t.right; else return t.setValue(value); } while (t != null); } Entry<K,V> e = new Entry<K,V>(key, value, parent); //生成一个节点 if (cmp < 0) parent.left = e; else parent.right = e; //指向最新节点 fixAfterInsertion(e); //修正 树结构 size++; modCount++; return null; }
2:插入后修正树的结构,TreeMap默认插入的都是红色的节点,因为插入黑色会破坏,路径上黑色的节点数
/** From CLR */ private void fixAfterInsertion(Entry<K,V> x) { x.color = RED; //默认红色 // 插入的节点不为null和不是根节点,其父亲节点是红色,那么就会两个红节点想连, //需要调整 while (x != null && x != root && x.parent.color == RED) { if (parentOf(x) == leftOf(parentOf(parentOf(x)))) { // 父亲是左孩子 Entry<K,V> y = rightOf(parentOf(parentOf(x))); //父亲的兄弟节点 if (colorOf(y) == RED) { //颜色为红 那么就是 父叔都为红 那么父叔变黑,祖父变红 setColor(parentOf(x), BLACK); setColor(y, BLACK); setColor(parentOf(parentOf(x)), RED); x = parentOf(parentOf(x)); } else { // 叔为黑或者不存在 if (x == rightOf(parentOf(x))) { //插入节点是右孩子 x = parentOf(x); // x的父节点设置为x rotateLeft(x); //左旋 变成都在左边 } // 都在左边 右旋 setColor(parentOf(x), BLACK); setColor(parentOf(parentOf(x)), RED); rotateRight(parentOf(parentOf(x))); //右旋 } } else { 父亲是右孩子 Entry<K,V> y = leftOf(parentOf(parentOf(x))); // 叔节点 if (colorOf(y) == RED) { //叔节点是红色 叔父节点都是红色 setColor(parentOf(x), BLACK); setColor(y, BLACK); setColor(parentOf(parentOf(x)), RED); x = parentOf(parentOf(x)); } else { // 叔节点是黑色或者为null if (x == leftOf(parentOf(x))) { // 插入节点是左孩子 x = parentOf(x); rotateRight(x); } // 父亲和孩子都在右边 setColor(parentOf(x), BLACK); setColor(parentOf(parentOf(x)), RED); rotateLeft(parentOf(parentOf(x))); } } } root.color = BLACK; // 把根节点变黑 }
1:考虑llr,就是插入节点是左孩子,的父亲是左孩子,红色,插入点的叔叔不存在火为黑,就必须右旋
/** From CLR */ private void rotateRight(Entry<K,V> p) { //p是插入节点的祖父节点 if (p != null) { Entry<K,V> l = p.left; // 插入节点的父亲 p.left = l.right; // 插入节点的兄弟变成祖父的左孩子 if (l.right != null) l.right.parent = p; // l.parent = p.parent; if (p.parent == null) // p的父亲为null,p其实就是跟节点 root = l; // l变成根节点 else if (p.parent.right == p) // p.parent.right = l; else p.parent.left = l; l.right = p; // p作为l的右孩子 p.parent = l; // p的父亲指向l } }
2:lrR,插入节点是右孩子,父亲是左孩子, 先左旋转换成llr型,然后按照上面的右旋即可
/** From CLR */ private void rotateLeft(Entry<K,V> p) { // 插入节点父亲 if (p != null) { Entry<K,V> r = p.right; // 插入节点 p.right = r.left; // 插入节点的做孩子付给父亲的右孩子 如图p.letf = x if (r.left != null) // x为null r.left.parent = p; // r.parent = p.parent; // 插入节点的父亲指向g 即使图中的p的父亲 if (p.parent == null) // 根节点 root = r; else if (p.parent.left == p) // p.parent.left = r; else p.parent.right = r; r.left = p; // r的左孩子为p 就是图中n-》p p.parent = r; //指定p的父亲节点为插入节点 } }
上面都是父亲节点是左孩子的情况,下面来看修正父亲节点是右孩子的情况
} else { 父亲是右孩子 Entry<K,V> y = leftOf(parentOf(parentOf(x))); // 叔节点 if (colorOf(y) == RED) { //叔节点是红色 叔父节点都是红色 setColor(parentOf(x), BLACK); setColor(y, BLACK); setColor(parentOf(parentOf(x)), RED); x = parentOf(parentOf(x)); } else { // 叔节点是黑色或者为null if (x == leftOf(parentOf(x))) { // 插入节点是左孩子 x = parentOf(x); rotateRight(x); } // 父亲和孩子都在右边 setColor(parentOf(x), BLACK); setColor(parentOf(parentOf(x)), RED); rotateLeft(parentOf(parentOf(x))); } } }
图示:
相关推荐
Java源代码是编程世界的基石,它是Java程序员用Java语言编写的程序文本,包含了类、方法、变量等元素,是理解程序逻辑和功能的核心。在Java编程中,源代码通常以`.java`为扩展名,经过Java编译器的处理,会被转化为...
以下是对"字典源代码--JAVA关于小字典的几个源代码"的详细解释: 1. **Map接口**: Map是Java集合框架的一部分,它定义了存储键值对的方法。主要方法包括`put(key, value)`用于添加元素,`get(key)`用于根据键获取值...
### 通过分析JDK源代码研究TreeMap红黑树算法实现 #### 一、TreeMap与TreeSet的关系 TreeMap 和 TreeSet 是 Java 集合框架中的重要成员,它们提供了基于红黑树的数据结构实现。从给定部分源代码可以看到,TreeSet ...
本资源"数据结构(Java版)源代码"提供了以Java语言实现的数据结构的详细实现,对于学习和理解数据结构有着重要的价值。 1. **数组**:数组是最基本的数据结构,它是一系列相同类型元素的集合,可以通过索引来访问每...
Java课程设计源代码是学习和理解Java编程语言深入精髓的重要资源。这些源代码实例涵盖了Java的基础到高级特性,为初学者提供了丰富的实践素材,同时也为有一定经验的开发者提供了参考和灵感。下面将详细阐述Java课程...
这段代码会根据`tree_map_data`中的部门和分类数量生成一个TreeMap,每个矩形的面积代表对应的数量,颜色和大小的深浅则可以用来表示其他属性,如销售额或利润。 除了Matplotlib,还有其他的Python可视化库,比如...
"Java核心技术源代码.rar"这个压缩包很可能是包含了一些关于Java基础到高级技术的示例代码或者一个完整的项目源码,用于帮助学习者深入理解Java编程。在这个压缩包中,"CoreJava源代码"可能包含了Java核心类库的实现...
在开发过程中,你可能需要查看Treemap-4.1.2中的源代码来了解这个特定版本的实现细节,如优化、异常处理、线程安全措施等。这些源代码也可能包含了一些示例或者API的使用说明,帮助开发者更好地理解和使用这个特定...
这份“Java数据结构与算法+源代码高清版”资源旨在帮助开发者深入理解并掌握这些关键概念。 首先,让我们来探讨数据结构。数据结构是组织和存储数据的方式,它为算法提供了基础。常见的数据结构包括数组、链表、栈...
本资源“java数据结构源代码”聚焦于用Java实现的数据结构,包括树、排序、查找以及容器等核心概念。下面将对这些知识点进行详细的解读。 首先,**树数据结构**是计算机科学中非常重要的一种非线性结构,它由节点...
本压缩包包含了一系列关于Java基础语法的源代码示例,旨在帮助初学者深入理解和掌握Java编程的核心概念。以下将针对每个章节的可能内容进行详细阐述: 1. **Chapter 1:基础语法** - 变量声明与初始化:包括基本...
在这个案例中,“学生信息,用treemap做的”可能是一个包含具体实现的Java源代码文件,它演示了上述逻辑。通过阅读和分析这个文件,你可以更深入地了解如何在实际项目中应用`TreeMap`来处理学生信息数据。 总结来说...
Java 类的源代码文件是程序员编写程序的基本单元,它们以.java为扩展名,包含了Java语言的语法结构,用于定义对象、方法和变量等。在这个压缩包中,我们可能找到了作者自己编写的关于Java集合类的实例源代码。Java...
Java基础教程源代码是学习Java编程语言的重要参考资料,它涵盖了Java的基本操作,旨在帮助初学者理解和掌握编程概念。在这个教程中,你可以通过实际的代码示例来了解和实践各种Java编程技术。以下是一些关键的知识点...
Java编程新手自学手册源代码是为初学者设计的一份宝贵资源,它涵盖了Java语言的基础到进阶知识,帮助读者通过实践来理解编程概念。这份源代码包含了一系列的示例程序和练习,旨在辅助读者深入学习Java编程语言。 一...
源代码集合包含了书中所有示例和练习,对于学习和掌握Java编程有着极大的帮助。以下是这些源代码中涉及的一些关键知识点: 1. **多线程编程**:Java以其内置的多线程支持而闻名。在《CoreJava卷Ⅱ》中,你会看到...
TreeMap是一种有效的数据可视化方法,尤其适用于展示层次结构数据或比较不同类别的相对大小。在这个案例中,我们将探讨如何使用Python中的`Matplotlib`库来实现TreeMap,同时利用提供的`products.csv`, `aisles.csv`...
《Core Java 2》是Java开发领域的一本经典著作,分为卷一《基础知识》和卷二《高级特性》,深入浅出地介绍了Java编程的核心概念和技术。...同时,书中丰富的示例代码和源代码分析有助于加深理解,提升实战能力。
3. **集合框架**:Java集合框架是处理对象集合的重要工具,源代码可能会涉及到ArrayList、LinkedList、HashMap、TreeMap等数据结构的使用。 4. **多线程**:Java支持并发编程,源码可能涵盖线程的创建、同步、锁...
这个压缩包文件包含了多种Java源代码实例,是初学者探索和学习Java编程的理想资源。以下将详细解析这些源代码可能涉及的知识点,以帮助你更好地理解和应用Java。 1. **基础语法**:所有编程语言都有其基本的语法...