因为最近学习到Java中的容器,TreeMap不是很了解底层。值知道其底层的数据结构是红黑树。之前学习数据结构,学到平衡二叉树就没有往下面继续学,自然也不知道什么是B+树,B-树,红黑树,今天找了个教程看了一下什么是红黑树,原来就是要求不太严格的平衡二叉树。下面是我今天做的笔记。
红黑树会自动排序。如果是字符串就按照字母的自然顺序排序,如果是数字,就按照数字的自然顺序排序。如果传进去的是一个对象,会报错,因为没有办法排序,但是
这个时候可以重新CompareTo方法。来判断插入的节点到底是在左边还是在右边。
红黑树就是帮助大家提高搜索效率。一亿条数据要找一个,可能只需要20几次。
(1) 每个节点是黑色或者是红色
(2) 根节点是黑色
(3) 每个叶子节点(NIL)是黑色,【注意:这里叶子节点,是指为空】
(4) 如果一个节点是红色的,则它的子节点必须是黑色的。【注意:这里反过不来行】
(5) 从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。
(这里就是说一个跟节点到它子孙的所有叶节点之间有相同数目的黑节点)
(6) 和平衡二叉树的区别:AVL树的左右子树之差小于2。红黑树左右子树之间不能超过2倍。如左子树高度为3,则右子树高度不能超过6。
二者的平均搜索效率是相同的,但是极端情况下,红黑树比AVL差一点。
那为什么AVL这么完美,还要研究红黑数??
AVL树在插入一个节点的时候,效率比较低,可能要旋转的次数比较多。还可能影响到上面的节点。
任何一个节点插入进来,都会把它当成一个红节点。如果插入节点的父节点是黑色的,直接插入就可以;
(1) 如果插入节点的父节点是红色的,且叔叔(父亲的兄弟)节点也是红色
处理策略
1. 将爹设置为黑色
2. 将叔叔也设置为黑色
3. 将爷爷设置成红色
(2) 如果插入节点的父节点是红色的,且叔叔节点是黑色,且当前节点是其父亲节点的右孩子。
处理策略
1. 将父节点作为新的当前节点
2. 以新的当前节点为支点进行左旋
(3) 如果插入节点的父节点是红色的,且叔叔节点是黑色,插入节点是父节点的左孩子
处理策略
1. 将父节点设置为黑色
2.将爷爷节点设置为红色
3. 以爷爷节点为支点进行右旋
详细过程参考自己的笔记本,还有这个视频连接红黑树详细讲解
其实Java中的TreeMap的底层封装的就是treemap。
下面是treemap的常规操作。主要是排序的部分。
package com.map;import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;public class TreeMapDemo {public static void main(String[] args) {// TODO Auto-generated method stub/*treemap的底层数据结构是红黑树,所以会默认排序* 下面这个输出我们可以看出,它会默认按照键的字母顺序排序* (这个叫按照自然顺序排序)* */TreeMap<String,String> tmap=new TreeMap<String,String>();tmap.put("jack", "周杰伦");tmap.put("marry", "zhangsna");tmap.put("rose", "xiaohong");tmap.put("free", "mianfei");tmap.put("jack", "chenhao");//这里也是会把周杰伦覆盖掉System.out.println(tmap);Set<Entry<String, String>> entrys = tmap.entrySet();for(Entry<String, String> entry:entrys){System.out.println(entry);}}}
package com.map;import java.util.TreeMap;public class TreeMapDemo2 {public static void main(String[] args) {// TODO Auto-generated method stubTreeMap<Person, String> pdata=new TreeMap<Person, String>();pdata.put(new Person("zhangsan",20), "张三");pdata.put(new Person("orese",32), "李四");pdata.put(new Person("marry",25), "玛丽");pdata.put(new Person("zhaoliu",20), "赵六");//这里直接输出会报错。java.lang.ClassCastException。类型转换错误/*因为treemap里面会自动按照键的自然顺序排序,如果是数字就按照数字排序*是字符串就按照字母的顺序排序,但是此时我们存的是Person对象的实例,默认*没有办法排序,此时可能需要自己重写compareTo比较器进行排序*/System.out.println(pdata);}}
class Person implements Comparable<Person>{private String name;private int age;public Person(String name, int age) {super();this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic int compareTo(Person o) {// TODO Auto-generated method stubif(this.age-o.getAge()>0){return 1;//放到右边}else if(this.age-o.getAge()<0){return -1;//放到左边}return 0;}}