Java实现红黑树

简介: 红黑树概要二叉查找树实现了基本操作时间复杂度O(h),但是树的高度h在最坏的情况下可能变为n红黑树是一种平衡二叉树,可以保证树的高度 h = lg(N)红黑树的性质红黑树为每个节点添加了颜色存储位,确保了任何一个从根到叶子的路径长度不会比其他路径长出2倍每个节点是红色或者黑色根节点是黑色的叶子节点是黑色的红色节点的子节点都是黑色的当前节点到其后代叶子节点的所有简单路径路的黑色节点数目相同性质4确保了根节点到任意叶子节点的路径长度不会比到其他叶子节点的路径长度长出2倍。

红黑树概要

  • 二叉查找树实现了基本操作时间复杂度O(h),但是树的高度h在最坏的情况下可能变为n
  • 红黑树是一种平衡二叉树,可以保证树的高度 h = lg(N)

红黑树的性质

红黑树为每个节点添加了颜色存储位,确保了任何一个从根到叶子的路径长度不会比其他路径长出2倍

  1. 每个节点是红色或者黑色
  2. 根节点是黑色的
  3. 叶子节点是黑色的
  4. 红色节点的子节点都是黑色的
  5. 当前节点到其后代叶子节点的所有简单路径路的黑色节点数目相同

性质4确保了根节点到任意叶子节点的路径长度不会比到其他叶子节点的路径长度长出2倍。例如,黑高为3的树最短路径为2(黑-黑-黑(外部节点)),最长路径为4(黑-红-黑-红-黑(外部节点)),从而一棵n个节点的红黑树高度最大为2lg(n+1)

红黑树实现代码

经过旋转后,二叉搜索树的性质保持

public class RedBlackTree {
    private TreeNode root = TreeNode.nil;
    public TreeNode minimum() {
        TreeNode node = minimum(root);
        if (node == TreeNode.nil) {
            return null;
        }
        return node;
    }
    public TreeNode maximum() {
        TreeNode node = maximum(root);
        if (node == TreeNode.nil) {
            return null;
        }
        return node;
    }
    public TreeNode successor(TreeNode x) {
        if (x == TreeNode.nil) {
            return null;
        }
        if (x.right != TreeNode.nil) {
            return minimum(x.right);
        } else {
            TreeNode y = x.p;
            while (y != null && x == y.right) {
                x = y;
                y = y.p;
            }
            return y;
        }
    }
    public TreeNode predecessor(TreeNode x) {
        if (x == TreeNode.nil) {
            return null;
        }
        if (x.left != TreeNode.nil) {
            return maximum(x.left);
        } else {
            TreeNode y = x.p;
            while (y != null && x == y.left) {
                x = y;
                y = y.p;
            }
            return y;
        }
    }
    public TreeNode search(int key) {
        TreeNode node = root;
        while (node != TreeNode.nil) {
            if (key < node.key) {
                node = node.left;
            } else if (key > node.key) {
                node = node.right;
            } else {
                return node;
            }
        }
        return null;
    }
    public void insert(TreeNode node) {
        TreeNode p = TreeNode.nil;
        TreeNode t = root;
        while (t != TreeNode.nil) {
            p = t;
            if (node.key < t.key) {
                t = t.left;
            } else {
                t = t.right;
            }
        }
        node.p = p;
        if (p == TreeNode.nil) {
            root = node;
        } else if (node.key > p.key) {
            p.right = node;
        } else {
            p.left = node;
        }
        node.color = Color.RED;
        node.left = TreeNode.nil;
        node.right = TreeNode.nil;
        insertionFixup(node);
    }
    public void delete(TreeNode z) {
        TreeNode y = z;
        TreeNode x = TreeNode.nil;
        Color originalColor = y.color;
        if (z.left == TreeNode.nil) {
            x = z.right;
            transplant(z, z.right);
        } else if (z.right == TreeNode.nil) {
            x = z.left;
            transplant(z, z.left);
        } else {
            y = minimum(z.right);
            originalColor = y.color;
            x = y.right;
            if (y.p == z) {
                x.p = y;
            } else {
                transplant(y, y.right);
                y.right = z.right;
                y.right.p = y;
            }
            transplant(z, y);
            y.left = z.left;
            y.left.p = y;
            y.color = z.color;
        }
        if (originalColor == Color.BLACK) {
            deletionFixup(x);
        }
    }
    private void deletionFixup(TreeNode x) {
        while (x != root && x.color == Color.BLACK) {
            if (x == x.p.left) {
                TreeNode w = x.p.right;
                if (w.color == Color.RED) {
                    w.color = Color.BLACK;
                    w.p.color = Color.RED;
                    leftRotate(x.p);
                    w = x.p.right;
                } else if (w.left.color == Color.BLACK && w.right.color == Color.BLACK) {
                    w.color = Color.RED;
                    x = x.p;
                } else if (w.right.color == Color.BLACK) {
                    w.left.color = Color.BLACK;
                    w.color = Color.RED;
                    rightRotate(w);
                    w = x.p.right;
                } else {
                    w.color = x.p.color;
                    x.p.color = Color.BLACK;
                    w.right.color = Color.BLACK;
                    leftRotate(x.p);
                    x = root;
                }
            } else {
                TreeNode w = x.p.left;
                if (w.color == Color.RED) {
                    w.color = Color.BLACK;
                    w.p.color = Color.RED;
                    rightRotate(x.p);
                    w = x.p.left;
                } else if (w.right.color == Color.BLACK && w.left.color == Color.BLACK) {
                    w.color = Color.RED;
                    x = x.p;
                } else if (w.left.color == Color.BLACK) {
                    w.right.color = Color.BLACK;
                    w.color = Color.RED;
                    leftRotate(w);
                    w = x.p.left;
                } else {
                    w.color = x.p.color;
                    x.p.color = Color.BLACK;
                    w.left.color = Color.BLACK;
                    rightRotate(x.p);
                    x = root;
                }
            }
        }
        x.color = Color.BLACK;
    }
    private TreeNode minimum(TreeNode x) {
        if (root == TreeNode.nil) {
            return TreeNode.nil;
        }
        while (x.left != TreeNode.nil) {
            x = x.left;
        }
        return x;
    }
    private TreeNode maximum(TreeNode x) {
        if (x == TreeNode.nil) {
            return TreeNode.nil;
        }
        while (x.right != TreeNode.nil) {
            x = x.right;
        }
        return x;
    }
    private void transplant(TreeNode u, TreeNode v) {
        if (u.p == TreeNode.nil) {
            root = v;
        } else if (u == u.p.left) {
            u.p.left = v;
        } else {
            u.p.right = v;
        }
        v.p = u.p;
    }

    private void leftRotate(TreeNode x) {
        TreeNode y = x.right;
        x.right = y.left;
        if (y.left != TreeNode.nil) {
            y.left.p = x;
        }
        if (x.p == TreeNode.nil) {
            root = y;
        } else if (x == x.p.left) {
            x.p.left = y;
        } else {
            x.p.right = y;
        }
        y.p = x.p;
        y.left = x;
        x.p = y;
    }

    private void rightRotate(TreeNode x) {
        TreeNode y = x.left;
        x.left = y.right;
        if (y.right != TreeNode.nil) {
            y.right.p = x;
        }
        if (x.p == TreeNode.nil) {
            root = y;
        } else if (x == x.p.left) {
            x.p.left = y;
        } else {
            x.p.right = y;
        }
        y.p = x.p;
        y.right = x;
        x.p = y;
    }

    private void insertionFixup(TreeNode z) {
        while (z.p.color == Color.RED) {
            if (z.p == z.p.p.left) {
                TreeNode y = z.p.p.right;
                if (y.color == Color.RED) {
                    z.p.color = Color.BLACK;
                    y.color = Color.BLACK;
                    z.p.p.color = Color.RED;
                    z = z.p.p;
                } else if (z == z.p.right) {
                    z = z.p;
                    leftRotate(z);
                } else {
                    z.p.color = Color.BLACK;
                    z.p.p.color = Color.RED;
                    rightRotate(z.p.p);
                }
            } else {
                TreeNode y = z.p.p.left;
                if (y.color == Color.RED) {
                    z.p.color = Color.BLACK;
                    y.color = Color.BLACK;
                    z.p.p.color = Color.RED;
                    z = z.p.p;
                } else if (z == z.p.left) {
                    z = z.p;
                    rightRotate(z);
                } else {
                    z.p.color = Color.BLACK;
                    z.p.p.color = Color.RED;
                    leftRotate(z.p.p);
                }
            }
        }
        root.color = Color.BLACK;
    }

    @Override
    public String toString() {
        Queue<TreeNode> q = new LinkedList<TreeNode>();
        StringBuilder sb = new StringBuilder();
        q.offer(root);
        while (!q.isEmpty()) {
            TreeNode node = q.poll();
            if (node == TreeNode.nil) {
                sb.append("#");
                continue;
            } else {
                sb.append(node);
                q.offer(node.left);
                q.offer(node.right);
            }
        }
        int p = sb.length();
        while (p > 0) {
            if (sb.charAt(p - 1) != '#') {
                break;
            }
            p--;
        }
        return sb.substring(0, p).toString();
    }

    static class TreeNode {
        public static final TreeNode nil = new TreeNode(0);
        Color color = Color.BLACK;
        int key;
        TreeNode left = nil;
        TreeNode right = nil;
        TreeNode p = nil;
        public TreeNode(int key) {
            this.key = key;
        }
        @Override
        public String toString() {
            return "(" + key + " " + color + ")";
        }
    }
    enum Color {
        RED, BLACK;
    }
    public static void main(String[] args) {
        TreeNode root = new TreeNode(0);
        TreeNode one = new TreeNode(1);
        TreeNode two = new TreeNode(2);
        TreeNode three = new TreeNode(3);
        TreeNode four = new TreeNode(4);
        TreeNode five = new TreeNode(5);
        RedBlackTree rbt = new RedBlackTree();
        rbt.insert(one);
        rbt.insert(three);
        rbt.insert(root);
        rbt.insert(four);
        rbt.insert(five);
        rbt.insert(two);
        printTree(rbt);
        rbt.delete(five);
        printTree(rbt);
    }
}  
目录
相关文章
|
1月前
|
Java 开发者
在Java的集合世界里,Set以其独特的特性脱颖而出,它通过“哈希魔法”和“红黑树防御”两大绝技
【10月更文挑战第13天】在Java的集合世界里,Set以其独特的特性脱颖而出。它通过“哈希魔法”和“红黑树防御”两大绝技,有效抵御重复元素的侵扰,确保集合的纯洁性和有序性。无论是“人海战术”还是“偷梁换柱”,Set都能从容应对,成为开发者手中不可或缺的利器。
31 6
|
3月前
|
Java
【Java集合类面试十一】、HashMap为什么用红黑树而不用B树?
HashMap选择使用红黑树而非B树,是因为红黑树在内存中实现简单,节点更小,占用内存少,且在插入、删除和查找操作上提供更好的平衡性能。
|
3月前
|
存储 开发者 C#
WPF与邮件发送:教你如何在Windows Presentation Foundation应用中无缝集成电子邮件功能——从界面设计到代码实现,全面解析邮件发送的每一个细节密武器!
【8月更文挑战第31天】本文探讨了如何在Windows Presentation Foundation(WPF)应用中集成电子邮件发送功能,详细介绍了从创建WPF项目到设计用户界面的全过程,并通过具体示例代码展示了如何使用`System.Net.Mail`命名空间中的`SmtpClient`和`MailMessage`类来实现邮件发送逻辑。文章还强调了安全性和错误处理的重要性,提供了实用的异常捕获代码片段,旨在帮助WPF开发者更好地掌握邮件发送技术,提升应用程序的功能性与用户体验。
68 0
|
3月前
|
存储 Java 开发者
揭秘!HashMap底层结构大起底:从数组到链表,再到红黑树,Java性能优化的秘密武器!
【8月更文挑战第24天】HashMap是Java集合框架中的核心组件,以其高效的键值对存储和快速访问能力广受开发者欢迎。在JDK 1.8及以后版本中,HashMap采用了数组+链表+红黑树的混合结构,实现了高性能的同时解决了哈希冲突问题。数组作为基石确保了快速定位;链表则用于处理哈希冲突;而当链表长度达到一定阈值时,通过转换为红黑树进一步提升性能。此外,HashMap还具备动态扩容机制,当负载因子超过预设值时自动扩大容量并重新哈希,确保整体性能。通过对HashMap底层结构的深入了解,我们可以更好地利用其优势解决实际开发中的问题。
109 0
|
存储 算法 Java
深入解析 Java 数据结构:红黑树的特点与应用
红黑树(Red-Black Tree)是一种自平衡的二叉搜索树,它在 Java 编程中扮演着重要的角色,用于高效地存储和管理数据。红黑树的特点使其在查找、插入和删除操作中保持相对平衡,从而提供了稳定且高效的性能。本文将深入探讨红黑树的特点、用法、实现方式以及在实际应用中的优势。
|
6月前
|
存储 算法 安全
【Java编程进阶之路 02】深入探索:红黑树如何重塑哈希表的性能边界
JDK 1.8之后,HashMap引入红黑树来优化性能,当链表长度超过阈值(默认为8)时,链表会转换为红黑树,从而提高高冲突时的查询效率。同时,HashMap也采用了扰动函数来增加哈希值的随机性,使键值对更均匀分布,提升性能。
82 0
|
6月前
|
存储 Java
Java TreeMap:基于红黑树的排序映射解析
Java TreeMap:基于红黑树的排序映射解析
|
6月前
|
安全 Java
Java TreeSet:基于红黑树的排序集合解析
Java TreeSet:基于红黑树的排序集合解析
|
存储 缓存 算法
【JavaSE专栏54】Java集合类TreeMap解析,基于红黑树的键值对存储结构
【JavaSE专栏54】Java集合类TreeMap解析,基于红黑树的键值对存储结构
|
存储 安全 Java
【JavaSE专栏52】Java集合类TreeSet解析,基于红黑树实现的有序非重集合
【JavaSE专栏52】Java集合类TreeSet解析,基于红黑树实现的有序非重集合
119 0
下一篇
无影云桌面