`
iluoxuan
  • 浏览: 583417 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

TreeMap源代码

 
阅读更多

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)));
                }
            }
        }

 图示:

 



 

 

 

 

 

 

 

 

 

 
 

 

 

  • 大小: 24.8 KB
  • 大小: 31.3 KB
  • 大小: 24.5 KB
  • 大小: 28.3 KB
分享到:
评论

相关推荐

    java源代码,java源代码

    Java源代码是编程世界的基石,它是Java程序员用Java语言编写的程序文本,包含了类、方法、变量等元素,是理解程序逻辑和功能的核心。在Java编程中,源代码通常以`.java`为扩展名,经过Java编译器的处理,会被转化为...

    字典源代码--JAVA关于小字典的几个源代码

    以下是对"字典源代码--JAVA关于小字典的几个源代码"的详细解释: 1. **Map接口**: Map是Java集合框架的一部分,它定义了存储键值对的方法。主要方法包括`put(key, value)`用于添加元素,`get(key)`用于根据键获取值...

    通过分析_JDK_源代码研究_TreeMap_红黑树算法实现.docx

    ### 通过分析JDK源代码研究TreeMap红黑树算法实现 #### 一、TreeMap与TreeSet的关系 TreeMap 和 TreeSet 是 Java 集合框架中的重要成员,它们提供了基于红黑树的数据结构实现。从给定部分源代码可以看到,TreeSet ...

    数据结构(Java版)源代码

    本资源"数据结构(Java版)源代码"提供了以Java语言实现的数据结构的详细实现,对于学习和理解数据结构有着重要的价值。 1. **数组**:数组是最基本的数据结构,它是一系列相同类型元素的集合,可以通过索引来访问每...

    JAVA课程设计源代码

    Java课程设计源代码是学习和理解Java编程语言深入精髓的重要资源。这些源代码实例涵盖了Java的基础到高级特性,为初学者提供了丰富的实践素材,同时也为有一定经验的开发者提供了参考和灵感。下面将详细阐述Java课程...

    Python TreeMap可视化方案数据源(实现代码,请看我博客专栏《机器学习》)

    这段代码会根据`tree_map_data`中的部门和分类数量生成一个TreeMap,每个矩形的面积代表对应的数量,颜色和大小的深浅则可以用来表示其他属性,如销售额或利润。 除了Matplotlib,还有其他的Python可视化库,比如...

    Java核心技术源代码.rar

    "Java核心技术源代码.rar"这个压缩包很可能是包含了一些关于Java基础到高级技术的示例代码或者一个完整的项目源码,用于帮助学习者深入理解Java编程。在这个压缩包中,"CoreJava源代码"可能包含了Java核心类库的实现...

    Treemap-4.1.2

    在开发过程中,你可能需要查看Treemap-4.1.2中的源代码来了解这个特定版本的实现细节,如优化、异常处理、线程安全措施等。这些源代码也可能包含了一些示例或者API的使用说明,帮助开发者更好地理解和使用这个特定...

    Java 数据结构与算法+源代码 高清版

    这份“Java数据结构与算法+源代码高清版”资源旨在帮助开发者深入理解并掌握这些关键概念。 首先,让我们来探讨数据结构。数据结构是组织和存储数据的方式,它为算法提供了基础。常见的数据结构包括数组、链表、栈...

    java数据结构源代码

    本资源“java数据结构源代码”聚焦于用Java实现的数据结构,包括树、排序、查找以及容器等核心概念。下面将对这些知识点进行详细的解读。 首先,**树数据结构**是计算机科学中非常重要的一种非线性结构,它由节点...

    java基础语法程序源代码

    本压缩包包含了一系列关于Java基础语法的源代码示例,旨在帮助初学者深入理解和掌握Java编程的核心概念。以下将针对每个章节的可能内容进行详细阐述: 1. **Chapter 1:基础语法** - 变量声明与初始化:包括基本...

    java treemap 学生信息

    在这个案例中,“学生信息,用treemap做的”可能是一个包含具体实现的Java源代码文件,它演示了上述逻辑。通过阅读和分析这个文件,你可以更深入地了解如何在实际项目中应用`TreeMap`来处理学生信息数据。 总结来说...

    java类的源代码文件

    Java 类的源代码文件是程序员编写程序的基本单元,它们以.java为扩展名,包含了Java语言的语法结构,用于定义对象、方法和变量等。在这个压缩包中,我们可能找到了作者自己编写的关于Java集合类的实例源代码。Java...

    java基础教程源代码

    Java基础教程源代码是学习Java编程语言的重要参考资料,它涵盖了Java的基本操作,旨在帮助初学者理解和掌握编程概念。在这个教程中,你可以通过实际的代码示例来了解和实践各种Java编程技术。以下是一些关键的知识点...

    java编程新手自学手册源代码

    Java编程新手自学手册源代码是为初学者设计的一份宝贵资源,它涵盖了Java语言的基础到进阶知识,帮助读者通过实践来理解编程概念。这份源代码包含了一系列的示例程序和练习,旨在辅助读者深入学习Java编程语言。 一...

    corejavaⅡ源代码

    源代码集合包含了书中所有示例和练习,对于学习和掌握Java编程有着极大的帮助。以下是这些源代码中涉及的一些关键知识点: 1. **多线程编程**:Java以其内置的多线程支持而闻名。在《CoreJava卷Ⅱ》中,你会看到...

    Python_TreeMap_可视化方案数据源(实现代码,请看我博客专栏《机器学习》)

    TreeMap是一种有效的数据可视化方法,尤其适用于展示层次结构数据或比较不同类别的相对大小。在这个案例中,我们将探讨如何使用Python中的`Matplotlib`库来实现TreeMap,同时利用提供的`products.csv`, `aisles.csv`...

    Core Java 2源代码

    《Core Java 2》是Java开发领域的一本经典著作,分为卷一《基础知识》和卷二《高级特性》,深入浅出地介绍了Java编程的核心概念和技术。...同时,书中丰富的示例代码和源代码分析有助于加深理解,提升实战能力。

    java核心技术第七版第二卷源代码.rar

    3. **集合框架**:Java集合框架是处理对象集合的重要工具,源代码可能会涉及到ArrayList、LinkedList、HashMap、TreeMap等数据结构的使用。 4. **多线程**:Java支持并发编程,源码可能涵盖线程的创建、同步、锁...

    与java有关的各类源代码

    这个压缩包文件包含了多种Java源代码实例,是初学者探索和学习Java编程的理想资源。以下将详细解析这些源代码可能涉及的知识点,以帮助你更好地理解和应用Java。 1. **基础语法**:所有编程语言都有其基本的语法...

Global site tag (gtag.js) - Google Analytics