红黑树插入操作分析及代码实现

来源:互联网 发布:重庆仙桃数据有限公司 编辑:程序博客网 时间:2024/06/08 06:22

首先说一下红黑树的五个性质:

1、每个结点要么是红色的,要么是黑色的;
2、根结点是黑色的;
3、每个叶结点,即空结点(NIL)是黑色的;
4、如果一个结点是红色的,那么它的两个子结点都是黑色的;
5、对每个结点,从该结点到其子结点的所有路径上包含相同数目的黑结点。


在对红黑树插入的时候,我们一般都会插入红色的结点,红黑树的插入主要有这几种情况:

1、插入的是根结点;

     此时,只会违反性质2,那么直接把此结点涂为黑色即可。

2、插入的结点的父节点是黑色的;

     此时什么都不需要做。

3、插入的结点的父节点是红色且叔父结点是红色;

     此时又分为几种情况:
          1)、父节点是祖父结点的左子树还是右子树;     
          2)、插入的结点是父节点的左子树还是右子树。
     无论哪种情况,解决策略都是:
          对插入的结点(当前结点)的父节点和叔父结点涂黑,祖父结点涂红,把当前结点指向祖父结点,递归执行第1种情况。

4、插入的结点的父节点是红色,叔父结点是黑色的。

     这种情况又分为以下几种情况:
     1)、插入结点为父结点的左结点,父节点为祖父结点的左结点;
          解决方案:父节点变黑,祖父结点变红,然后以祖父结点为支点右旋。
     2)、插入结点为父节点的右节点,父节点为祖父结点的左结点;
          解决方案:以当前结点的父节点为支点左旋,然后再以当前结点的左结点执行第1)种情况。
     3)、插入结点为父节点的左结点,父节点为祖父结点的右节点;
          解决方案:以当前结点的父节点为支点右旋,然后再以当前结点的右节点执行第4)中情况。
     4)、插入结点为父节点的右节点,父节点为祖父结点的右节点。
          解决方案:父节点变黑,祖父结点变红,然后以祖父结点为支点左旋。

代码实现如下:

package com.tyxh.rab;public class TreeNode {     public int data;     public TreeNode lchild;     public TreeNode rchild;     public TreeNode parent;     public boolean color;     public TreeNode( int data, TreeNode lchild, TreeNode rchild,              TreeNode parent, boolean color) {           this. data = data;           this. lchild = lchild;           this. rchild = rchild;           this. parent = parent;           this. color = color;     }     }

package com.tyxh.rab;public class BTTree {     public static final boolean RED = false;     public static final boolean BLACK = true;     private TreeNode root;     public BTTree() {           root = null;     }     public TreeNode grandParentNode(TreeNode node) {           // 获得祖父节点           return node. parent. parent;     }     public TreeNode uncleParentNode(TreeNode node) {           // 获得叔父节点           if (node. parent == grandParentNode(node). lchild)               return grandParentNode(node). rchild;           else               return grandParentNode(node). lchild;     }     // 左旋     private void singRotateLeft(TreeNode k2) {          TreeNode k1 = k2. rchild;          k2. rchild = k1. lchild;          k1. lchild = k2;     }     // 右旋     private void singRotateRight(TreeNode k2) {          TreeNode k1 = k2. lchild;          k2. lchild = k1. rchild;          k1. rchild = k2;     }     // 插入     // 1、新结点位于树的根上,没有父节点     public void insert_case1(TreeNode node) {           if (node. parent == null)              node. color = BLACK;           else              insert_case2(node);     }     // 2、新节点的父节点是黑色的     public void insert_case2(TreeNode node) {           if (node. parent. color == BLACK)               return;           else              insert_case3(node);     }     // 3、父节点是红色的,叔父节点也是红色的     public void insert_case3(TreeNode node) {           if (uncleParentNode(node) != null && uncleParentNode(node).color == RED ) {              node. parent. color = BLACK;              uncleParentNode(node). color = BLACK;              grandParentNode(node). color = RED;              insert_case1(grandParentNode(node));          } else              insert_case4(node);     }     // 4、父节点是红色的,叔父结点是黑色的或者为Nil,并且插入结点是父节点的右节点,父节点是祖父结点的左结点     public void insert_case4(TreeNode node) {           if (node == node. parent. rchild                   && node. parent == grandParentNode(node).lchild) {               // 以node.parent为结点左旋              singRotateLeft(node. parent);              node = node. lchild;          } else if (node == node. parent. lchild                   && node. parent == grandParentNode(node).rchild) {               // 以node.parent为结点右旋              singRotateRight(node. parent);              node = node. rchild;          }          insert_case5(node);     }     // 5、父亲结点是红色的,叔父是黑色的或者为Nil,并且插入结点是父节点的左结点,父节点是祖父结点的左结点     public void insert_case5(TreeNode node) {          node. parent. color = BLACK;          grandParentNode(node). color = RED;           if (node == node. parent. lchild                   && node. parent == grandParentNode(node).lchild) {               // 以祖父结点为结点右旋              singRotateRight(grandParentNode(node));          } else if (node == node. parent. rchild                   && node. parent == grandParentNode(node).rchild) {               // 以祖父结点为结点左旋              singRotateLeft(grandParentNode(node));          }     }     // 中序遍历     public void traversal() {          insubtree( root);     }     private void insubtree(TreeNode node) {           if (node == null)               return;          insubtree(node. lchild);          System. out.println(node. data + "、");          insubtree(node. rchild);     }}


0 0
原创粉丝点击