23树是具有绝对平衡的二叉树,即平衡因子是0(AVL树平衡因子控制在1),而红黑树模仿了23树的特征,但是不是真正意义上的平衡树。
画一下23树和红黑树比较一下就清楚了
如上图所示,左边的是23树,右边的是红黑树。
红黑树的特点是左倾斜,即右不能有红色节点,如果有红色节点 要进行如下操作。
1.左旋转,左节点是黑,右结点是红
旋转完成后,交换两个节点的颜色。
2.如果是这种情况,直接改变两个子节点的颜色为黑色,根节点变红,整个过程相当于颜色的翻转
3.还有这种左子树连续两个都是红色的,此时进行右旋转,然后交换颜色,再进行颜色翻转
完整代码如下
package rbtree;
public class Test1 {
static final boolean RED=true;
static final boolean BLACK=false;
static class Node{
int data;
Node left;
Node right;
boolean color;
public Node(int data){
this.data=data;
left=null;
right=null;
color=RED;
}
}
static class BST{
Node root;
//root结点
public BST(Node root){
this.root=root;
}
// 判断节点node的颜色
private boolean isRed(Node node){
if(node == null)
return BLACK;
return node.color;
}
// node x
// / \ 左旋转 / \
// T1 x ---------> node T3
// / \ / \
// T2 T3 T1 T2
private Node leftRotate(Node node){
Node x = node.right;
// 左旋转
node.right = x.left;
x.left = node;
x.color = node.color;
node.color = RED;
return x;
}
// node x
// / \ 右旋转 / \
// x T2 -------> y node
// / \ / \
// y T1 T1 T2
private Node rightRotate(Node node){
Node x = node.left;
// 右旋转
node.left = x.right;
x.right = node;
x.color = node.color;
node.color = RED;
return x;
}
//翻转
public void flipColor(Node node){
node.left.color=BLACK;
node.right.color=BLACK;
node.color=RED;
}
//插入操作
private Node insert(Node node,int data){
if (null==node){
return new Node(data);
}
if (node.data>data){
node.left=insert(node.left,data);
}else if (node.data<data){
node.right=insert(node.right,data);
}
if (isRed(node.right) && !isRed(node.left))
node = leftRotate(node);
if (isRed(node.left) && isRed(node.left.left))
node = rightRotate(node);
if (isRed(node.left) && isRed(node.right))
flipColor(node);
return node;
}
//插入操作
public void insert(int data){
insert(root,data);
root.color=BLACK;
}
}
public static void main(String[] args) {
BST bst = new BST(new Node(1));
bst.insert(2);
bst.insert(0);
bst.insert(4);
bst.insert(3);
bst.insert(60);
preorderTraversal(bst);
delete(bst,4);
preorderTraversal(bst);
// find(bst,4);
}
public static void preorderTraversal(BST bst){
preorderTraversal(bst.root);
}
private static void preorderTraversal(Node node){
if (node==null){
return;
}
//先序遍历
System.out.println(node.data);
preorderTraversal(node.left);
preorderTraversal(node.right);
}
//查找二叉树指定的数,根据二叉树左子节点小于父节点,和右子节点大于父节点的特性来递归查找
private static Node find(Node node,int data){
if (node.data==data){
return node;
}
if (node.data>data){
return find(node.left,data);
}else{
return find(node.right,data);
}
}
//查找二叉树指定的数,根据二叉树左子节点小于父节点,和右子节点大于父节点的特性来递归查找
public static void find(BST bst,int data){
Node node = find(bst.root, data);
// System.out.println(node.data);
}
public static void delete(BST bst,int data){
delete(bst.root,data);
}
//删除节点
private static void delete(Node node,int data){
Node n=node ;
Node fatherN=null;
while (n!=null&&n.data!=data){
fatherN=n;
if (n.data>data){
n=n.left;
}else{
n=n.right;
}
}
if (null==n){
return;
}
//第一种情况,两边节点都有
if (n.left!=null&&n.right!=null){
Node minNumber=n.right;//找出子节点
Node minNumberFather=n;//找出父节点
while (minNumber.left!=null){
minNumberFather=minNumber;
minNumber=minNumber.left;
}
// findMinNumber(minNumberFather,minNumber);
n.data=minNumber.data;//赋值
//下面做统一的判断
n=minNumber;
fatherN=minNumberFather;
}
Node chirld;
if (n.left!=null){
chirld=n.left;
return;
}else if (n.right!=null){
chirld=n.right;
}else {
chirld=null;
}
if (fatherN.left==n){
fatherN.left=chirld;
}else if (fatherN.right==n){
fatherN.right=chirld;
}else{
node=chirld;
}
}
}