码迷,mamicode.com
首页 > 编程语言 > 详细

红黑树的一个java实现

时间:2015-03-30 13:10:42      阅读:118      评论:0      收藏:0      [点我收藏+]

标签:

前几天闲来无事实现了一个红黑树,虽然感觉理解透了,但是真正写码的时候还是调了一个上午才调通,理论还是得联系实践才行啊。

另外可以看看234树,算是红黑树的一个变种,可以加深对红黑树的理解

 

红黑树性质

1)每个结点要么是红的,要么是黑的。

2)根结点是黑的。

3)每个叶结点,即空结点(NIL)是黑的。

4)如果一个结点是红的,那么它的俩个儿子都是黑的。

5)对每个结点,从该结点到其子孙结点的所有路径上包含相同数目的黑结点。

 

树的旋转

简单说就是把节点的一个子节点提上来当做主节点,原节点作为子节点

操作很简单,需要注意的一点就是树的深度的变化

 

插入节点

跟普通二叉树插入流程相似,只是需要多加一步平衡二叉树以满足红黑树的性质;

插入节点默认为红色,所以唯一可能破坏的性质为性质4

大致可以按照下面的几种情况处理:

 * 1. 如果父节点为黑色,平衡完成

 * 2. 如果叔节点为红色,向上循环

 * 3. 如果叔节点为黑色,把多余红色节点旋转到叔节点

 

删除节点

删除前面几步跟普通二叉树也一样,只删除节点后需要平衡二叉树

删除节点后会破坏性质5

删除后补充节点

 * 1. 如果只有一个孩子节点,直接提上孩子节点

 * 2. 如果没有孩子节点,找到后继节点,将后继节点的值替换到删除节点,然后删除后继几点

平衡删除后的树也可以大致分为以下几种情况:

 * 1. 如果补上来的节点为红色,直接变为黑色补足

 * 2. 如果兄弟节点为黑色,侄子也为黑色,将兄弟变为红色;

 *    与兄弟深度平衡后继续向上循环

 * 3. 如果兄弟为红色,或者侄子为红色,抢夺一个红色的节点补足自身

 

具体代码

package com.feinno.algorithmic.tree;

import java.util.LinkedList;
import java.util.List;
import java.util.Random;

/**
 * 
 * @author renzhaolong
 *
 * @param <K>
 * @param <V>
 */
public class RedBlackTree<K extends Comparable<K>, V> {
    
    //哨兵节点
    private Node nil = new Node();
    //根节点
    private Node root = nil;
    
    /**
     * 插入新值
     * @param key
     * @param value
     */
    public void insert(K key, V value) {
        Node newNode = new Node(key, value);
        if (root == nil) {
            root = newNode;
            root.color = Color.Black;
            return;
        }
        Node currentNode = root;
        newNode.color = Color.Red;
        while (currentNode != nil) {
            int compare = key.compareTo(currentNode.key);
            if (compare >= 0) {
                if (currentNode.rightChild != nil) {
                    currentNode = currentNode.rightChild;
                } else {
                    currentNode.rightChild = newNode;
                    newNode.parent = currentNode;
                    break;
                }
            } else {
                if (currentNode.leftChild != nil) {
                    currentNode = currentNode.leftChild;
                } else {
                    currentNode.leftChild = newNode;
                    newNode.parent = currentNode;
                    break;
                }
            }
        }
        if (currentNode.color == Color.Red) {
            insertBalance(newNode);
        }
    }
    
    /**
     * 添加节点后平衡红黑树
     * 如果父节点为红色,两个连续红色节点
     * 1. 如果父节点为黑色,平衡完成
     * 2. 如果叔节点为红色,向上循环
     * 3. 如果叔节点为黑色,把多余红色节点旋转到叔节点
     * @param node
     */
    private void insertBalance(Node node) {
        Node parent = node.parent;
        //如果父节点同为红色,违反红黑树性质
        while (node != root && node.parent != root && parent.color == Color.Red) {
            //if left child
            if (parent.parent.leftChild == parent) {
                Node y = parent.parent.rightChild;
                //如果叔父节点也为红色,祖父节点已满,需要向上分裂
                if (y.color == Color.Red) {
                    parent.color = Color.Black;
                    y.color = Color.Black;
                    parent.parent.color = Color.Red;
                    node = parent.parent;
                    parent = node.parent;
                } else { //否则通过旋转维持平衡
                    //if right child
                    if (parent.rightChild == node) {
                        parent = leftRotate(parent);
                    }
                    parent.color = parent.parent.color;
                    parent.parent.color = Color.Red;
                    parent = rightRotate(parent.parent);
                    break;
                }
            } else {
                Node y = parent.parent.leftChild;
                if (y.color == Color.Red) {
                    parent.color = Color.Black;
                    y.color = Color.Black;
                    parent.parent.color = Color.Red;
                    node = parent.parent;
                    parent = node.parent;
                } else {
                    if (parent.leftChild == node) {
                        parent = rightRotate(parent);
                    }
                    parent.color = parent.parent.color;
                    parent.parent.color = Color.Red;
                    parent = leftRotate(parent.parent);
                    break;
                }
            }
        }
        root.color = Color.Black;
    }
    
    /**
     * 删除key所在node
     * 如果节点不是子节点,需要确定后补节点
     * 1. 如果只有一个孩子节点,直接提上孩子节点
     * 2. 如果没有孩子节点,找到后继节点,将后继节点的值替换到删除节点,然后删除后继几点
     * @param key
     */
    public V delete(K key) {
        Node del = search(key);
        if (nil == del) {
            return null;
        }
        V result = del.value;
        if (del.leftChild != nil && del.rightChild != nil) {
            Node successor = getSuccessorNode(del);
            del.key = successor.key;
            del.value = successor.value;
            del = successor;
        }
        Node current;
        if (del.leftChild != nil) {
            current = del.leftChild;
        } else {
            current = del.rightChild;
        }
        current.parent = del.parent;
        if (current.parent.leftChild == del) {
            current.parent.leftChild = current;
        } else {
            current.parent.rightChild = current;            
        }
        //如果删除的是黑色节点,需要重新平衡
        if (del.color == Color.Black) {
            DeleteBalance(current);
        }
        
        return result;
    }
    
    /**
     * 删除节点后平衡红黑树
     * 删除节点的子树深度不够
     * 补足深度
     * 1. 如果节点为红色,直接变为黑色补足
     * 2. 如果兄弟节点为黑色,侄子也为黑色,将兄弟变为红色;
     *    与兄弟深度平衡后继续向上循环
     * 3. 如果兄弟为红色,或者侄子为红色,抢夺一个红色的节点补足自身
     * @param node
     */
    private void DeleteBalance(Node node) {
        while (node != root && node.color == Color.Black) {
            Node parent = node.parent;
            if (parent.leftChild == node) {
                Node right = parent.rightChild;
                if (right.color == Color.Red) {
                    right.color = Color.Black;
                    parent.color = Color.Red;
                    node = leftRotate(parent);
                    right = parent.rightChild;
                }
                if (right.leftChild.color == Color.Black &&
                        right.rightChild.color == Color.Black) {
                    right.color = Color.Red;
                    node = parent;
                    continue;
                } else {
                    if (right.rightChild.color == Color.Black) {
                        right.color = Color.Red;
                        right.leftChild.color = Color.Black;
                        right = rightRotate(right);
                    }
                    parent = leftRotate(parent);
                    parent.color = parent.leftChild.color;
                    parent.rightChild.color = Color.Black;
                    parent.leftChild.color = Color.Black;
                    break;
                }
            } else {
                Node left = parent.leftChild;
                if (left.color == Color.Red) {
                    left.color = Color.Black;
                    parent.color = Color.Red;
                    rightRotate(parent);
                    left = parent.leftChild;
                }
                if (left.leftChild.color == Color.Black &&
                        left.rightChild.color == Color.Black) {
                    left.color = Color.Red;
                    node = parent;
                    continue;
                } else {
                    if (left.leftChild.color == Color.Black) {
                        left.color = Color.Red;
                        left.rightChild.color = Color.Black;
                        left = leftRotate(left);
                    }
                    parent = rightRotate(parent);
                    parent.color = parent.rightChild.color;
                    parent.rightChild.color = Color.Black;;
                    parent.leftChild.color = Color.Black;
                    //node = parent;
                    break;
                }
            }
        }
        node.color = Color.Black;
    }
    
    /**
     * 获取当前节点的后继节点
     * @param node
     * @return
     */
    private Node getSuccessorNode(Node node) {
        if (node.rightChild == nil) {
            Node temp = node;
            while (temp.parent != nil) {
                if (temp.parent.leftChild == temp) {
                    return temp.parent;
                }
            }
            return nil;
        }
        if (node.rightChild != nil) {
            Node temp = node.rightChild;
            while (temp.leftChild != nil) {
                temp = temp.leftChild;
            }
            return temp;
        }
        return nil;
    }
    
    /**
     * 右旋
     * 把左子节点提上来
     * @param node
     * @return
     */
    private Node rightRotate(Node node) {
        Node left = node.leftChild;
        node.leftChild = left.rightChild;
        node.leftChild.parent = node;
        left.rightChild = node;
        left.parent = node.parent;
        node.parent = left;
        if (left.parent.leftChild == node) {
            left.parent.leftChild = left;
        } else {
            left.parent.rightChild = left;
        }
        return left;
    }
    
    /**
     * 左旋
     * 把右子节点提上来
     * @param node
     * @return
     */
    private Node leftRotate(Node node) {
        Node right = node.rightChild;
        node.rightChild = right.leftChild;
        node.rightChild.parent = node;
        right.leftChild = node;
        right.parent = node.parent;
        node.parent = right;
        if (right.parent.leftChild == node) {
            right.parent.leftChild = right;
        } else {
            right.parent.rightChild = right;
        }
        return right;
    }
    
    /**
     * 根据key获取value
     * @param key
     * @return
     */
    public V get(K key) {
        return search(key).value;
    }
    
    /**
     * 根据key查找Node
     * @param key
     * @return
     */
    private Node search(K key) {
        Node result = root;
        while (result != nil) {
            int compare = key.compareTo(result.key);
            if (compare == 0) {
                return result;
            } else if (compare > 0) {
                result = result.rightChild;
            } else {
                result = result.leftChild;
            }
        }
        return nil;
    }
    
    private boolean checkBalance() {
        if (root == nil) { return true; }
        if (root.color == Color.Red) { return false; } 
        int height = getNodeHeight(root); 
        if (-1 == height) {
            return false;
        }
        return true;
    }
    
    /**
     * 如果满足红黑树性质
     * 如果不满足,返回-1
     * @param node
     * @return
     */
    private int getNodeHeight(Node node) {
        if (node == nil) {
            return 0;
        }
        if (Color.Red == node.color && Color.Red == node.parent.color) {
            return -1;
        }
        int left = getNodeHeight(node.leftChild);
        if (-1 == left) {
            return -1;
        }
        int right = getNodeHeight(node.rightChild);
        if (left != right) {
            return -1;
        }
        if (Color.Red == node.color)
            return right;
        return right + 1;
    }
    
    private class Node implements Comparable<Node> {
        private Node parent = nil;
        private Node leftChild = nil;
        private Node rightChild = nil;
        private Color color = Color.Black;
        private K key;
        private V value;
        
        public Node(){}
        
        public Node(K key, V value) {
            this.key = key;
            this.value = value;
        }
        
        @Override
        public int compareTo(Node o) {
            return key.compareTo(o.key);
        }
        
        public String toString() {
            return "Key:" + key.toString() + " Color:" + color;
        }
    }
    private static enum Color {
        Red,
        Black
    }
    
    public static void main(String[] args) throws Exception {
        RedBlackTree<Integer, Integer> rb = new RedBlackTree<Integer, Integer>();
        List<Integer> keys = new LinkedList<Integer>();
        Random ran = new Random();
        
        for (int i = 0; i < 1000; i++) {
            int key = ran.nextInt(100000);
            rb.insert(key, 1);
            keys.add(key);
            if (rb.checkBalance() == false) {
                throw new Exception("error");
            } else {
                System.out.println("good:" + key);
            }
        }
        for (int key : keys) {
            rb.delete(key);
            if (rb.checkBalance() == false) {
                throw new Exception("error" + key);
            } else {
                //System.out.println("good");
            }
        }
    }
}

 

红黑树的一个java实现

标签:

原文地址:http://www.cnblogs.com/remagon/p/4377460.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!