红黑树插入操作分析及代码实现
来源:互联网 发布:重庆仙桃数据有限公司 编辑:程序博客网 时间: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
- 红黑树插入操作分析及代码实现
- 红黑树的插入操作--伪代码详细分析
- 红黑树插入删除节点过程分析 && C代码实现
- 直接插入排序算法分析、代码实现
- 插入排序伪代码及实现
- 【减治法】插入排序及C++代码实现
- 插入排序原理分析及Java实现
- 分页操作的分析及代码
- 分页操作的分析及代码
- 分页操作的分析及代码
- 红黑树插入操作和删除的代码
- 插入排序 代码分析
- 红黑树(基本性质及插入操作)
- 建链表及插入操作
- 数据结构&&AVL树原理、插入操作详解及实现
- 顺序表创建插入删除操作及实现
- AVL平衡树及插入操作的C语言实现
- python实现二叉树及插入,遍历操作
- EF6 SQL Logging – Part 2: Changing the content/formatting
- 圣斗士
- 理解Python的With语句
- 日期转化为字符串,字符串转化为日期
- android 保持菜单一直在底部的实现方法
- 红黑树插入操作分析及代码实现
- PHP查找中文字符的解决方案
- 黑马程序员_IO流(一)
- Android开源项目
- 第3周:计算闰年
- iOS:KVO的概述与使用
- FireFox中下载文件,文件名不能包含空格
- JDBC常见面试题集锦(二)
- 稍微深入点理解C++复制控制