红黑树的插入有自顶向下和自底向上两种方式,这里的插入实现是自顶向下的方式。
具体参考的博文地址:http://www.cnblogs.com/xuqiang/archive/2011/05/16/2047001.html
这篇博文将插入的几种case都讲的很清楚了。这里就直接贴代码了,代码有点丑。
package 第一章数据结构实现; public class RBTree { TreeNode head; //树的头节点 //创建红色的默认节点,但是未设置父节点 public TreeNode getNode(int val) { TreeNode defaultNode = new TreeNode(val); defaultNode.color = Color.RED; //默认为红色 return defaultNode; } //打印树 public void printTree(TreeNode node) { if(head==null) { System.out.println("树是空的,请确认init()方法已经执行!"); return ; } if(node==null) return ; else { //前序遍历 System.out.print("节点的值:"+node.val+" 节点的颜色:"+node.color); if(node.parent!=null) System.out.println(" 节点的父节点:"+node.parent.val); else System.out.println(" 这是根节点"); printTree(node.left); printTree(node.right); } } //=================================================================================================== //树的初始化 public void init(int[] arr) { for(int i=0;i<arr.length;++i) { insert(head,null,arr[i],-1); } } //inset 开始插入 ,lr为0代表left lr为1代表right lr为-1表示是根节点 public void insert(TreeNode head,TreeNode parent,int i,int lr) { if(head==null) { TreeNode x = getNode(i); x.parent=parent; head = x; if(lr==1) parent.right = head; else if(lr==0) parent.left = head; insert1(head); } else { //递归插入 if(i>head.val) insert(head.right,head,i,1); if(i<head.val) insert(head.left,head,i,0); } } //case1:插入的节点为根节点,将插入节点置为红色,前期x的父节点x.parent必须确定下来 public void insert1(TreeNode x) { if(x.parent==null) { x.color = Color.BLACK; head = x; //将首节点指向x return ; } else insert2(x); } //case2:插入的节点不为根节点 //且插入的节点的父节点为黑色的,那么红黑树是不用调节的 public void insert2(TreeNode x) { if(x.parent.color==Color.BLACK) return ; else insert3(x); } //case3如果插入节点的父节点为红色 ,违反父子节点都为红色的 // 如果叔叔节点为红色,只需将叔叔节点和父节点同时设为黑色,同时祖父节点设为红色 //但这会引入新问题,祖父节点和其自身父节点有可能都为红色,使用尾递归向上上滤 public void insert3(TreeNode x) { TreeNode par = x.parent; //父节点 TreeNode gra = par.parent; //祖父节点 TreeNode unc = (par==gra.left)? gra.right : gra.left; //叔叔节点 if(unc!=null && unc.color==Color.RED) { unc.color = Color.BLACK; par.color = Color.BLACK; gra.color = Color.RED; insert1(gra); //尾递归上滤 } else insert4(x); } //case4: 如果叔叔节点为黑色或者null public void insert4(TreeNode x) { TreeNode par = x.parent; //父节点 TreeNode gra = par.parent; //祖父节点//如果父节点是祖父节点的左节点,但x是父节点的右节点,交换x和其父节点,且x变为其原父节点的父节点 if(par==gra.left && x==par.right) { gra.left = x; x.left = par; x.parent = gra; par.right = null; par.parent = x; insert5(par); } //如果父节点是祖父节点的右节点,但是x是父节点的左节点,交换x和其父节点,且x变为祖父节点的右节点 else if(par==gra.right && x==par.left) { gra.right = x; x.right = par; x.parent = gra; par.left = null; par.parent = x; insert5(par); } else { insert5(x); //因为这个x节点有可能变为父节点了,所以要在insert5进行判断是否为变换后的父节点 } } public void insert5(TreeNode x) { TreeNode par = x.parent; //父节点 TreeNode gra = par.parent; //祖父节点 TreeNode ggra = gra.parent; //祖父节点的父节点 if(x==par.left) { gra.left = par.right; par.right = gra; par.parent = ggra; gra.parent = par; if(gra.left!=null) gra.left.parent = gra; //如果节点不为空更新父节点信息 //ggra.left = par; if(ggra==null) head = par; else { if(par.val>ggra.val) ggra.right = par; else ggra.left = par; } } else if(x==par.right) { //if(x.val==12) System.out.println("12的父节点的左节点:"+par.left.val); gra.right = par.left; par.left = gra; par.parent = ggra; gra.parent = par; if(gra.right!=null) gra.right.parent = gra; //要更新父节点信息 if(ggra==null) head = par; //根节点要重新指向 else { if(par.val>ggra.val) ggra.right = par; else ggra.left = par; } } //颜色变化 gra.color = Color.RED; par.color = Color.BLACK; } //======================================================================================================= public static void main(String[] args) { int[] arr = {5,3,1,7,9,6,15,12,14,13}; RBTree rbt = new RBTree(); rbt.init(arr); rbt.printTree(rbt.head); } //红黑树节点 private class TreeNode{ Color color=Color.RED; int val; TreeNode left; TreeNode right; TreeNode parent; TreeNode(int value) { val = value; } } //树节点枚举类 private enum Color{ RED,BLACK; } }
基于int[] arr = {5,3,1,7,9,6,15,12,14,13}构建的红黑树的打印的结果如下:
节点的值:7 节点的颜色:BLACK 这是根节点
节点的值:3 节点的颜色:RED 节点的父节点:7
节点的值:1 节点的颜色:BLACK 节点的父节点:3
节点的值:5 节点的颜色:BLACK 节点的父节点:3
节点的值:6 节点的颜色:RED 节点的父节点:5
节点的值:12 节点的颜色:RED 节点的父节点:7
节点的值:9 节点的颜色:BLACK 节点的父节点:12
节点的值:14 节点的颜色:BLACK 节点的父节点:12
节点的值:13 节点的颜色:RED 节点的父节点:14
节点的值:15 节点的颜色:RED 节点的父节点:14