Java红黑树的数据结构与算法解析

Java红黑树的数据结构与算法解析

红黑树简介

红黑树是一种平衡二叉搜索树,其中的每个节点上都有一个黑色或红色的标记,并且满足以下性质:

  1. 根节点是黑色的;
  2. 叶子节点是黑色的空节点(NULL);
  3. 如果一个节点是红色的,则其子节点必须是黑色的;
  4. 从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点;
  5. 新插入的节点默认是红色的。

具体来说,只有在删除或者某些特殊的插入操作之后,才会涉及到红黑树的平衡调整。

红黑树可以用于实现有序的映射表数据结构。Java 中的 TreeMap 就是基于红黑树实现的。

红黑树的基本操作

红黑树支持的操作包括:

  • add(e): 插入元素 e;
  • remove(e): 删除元素 e;
  • find(e): 查找元素 e;
  • floor(e): 返回小于等于 e 的最大元素;
  • ceiling(e): 返回大于等于 e 的最小元素;
  • lower(e): 返回小于 e 的最大元素;
  • higher(e): 返回大于 e 的最小元素;
  • first(): 返回树中最小元素;
  • last(): 返回树中最大元素。

这些操作都可以在 $O(\log(n))$ 的时间内完成。

红黑树实现示例

以下是基于 Java 实现的红黑树示例代码:

public class RedBlackTree<K extends Comparable<K>, V> {
    private static final boolean RED = true;
    private static final boolean BLACK = false;

    private class Node {
        public K key;
        public V value;
        public Node left, right;
        public boolean color;

        public Node(K key, V value) {
            this.key = key;
            this.value = value;
            left = null;
            right = null;
            color = RED;
        }
    }

    private Node root;
    private int size;

    public RedBlackTree() {
        root = null;
        size = 0;
    }

    public int getSize() {
        return size;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    private boolean isRed(Node node) {
        if (node == null)
            return BLACK;
        return node.color;
    }

    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;
    }

    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;
    }

    private void flipColors(Node node) {
        node.color = RED;
        node.left.color = BLACK;
        node.right.color = BLACK;
    }

    public void add(K key, V value) {
        root = add(root, key, value);
        root.color = BLACK;
    }

    private Node add(Node node, K key, V value) {
        if (node == null) {
            size++;
            return new Node(key, value);
        }

        if (key.compareTo(node.key) < 0)
            node.left = add(node.left, key, value);
        else if (key.compareTo(node.key) > 0)
            node.right = add(node.right, key, value);
        else
            node.value = value;

        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))
            flipColors(node);

        return node;
    }

    private Node getNode(Node node, K key) {
        if (node == null)
            return null;

        if (key.equals(node.key))
            return node;
        else if (key.compareTo(node.key) < 0)
            return getNode(node.left, key);
        else
            return getNode(node.right, key);
    }

    public boolean contains(K key) {
        return getNode(root, key) != null;
    }

    public V get(K key) {
        Node node = getNode(root, key);
        return node == null ? null : node.value;
    }

    public void set(K key, V newValue) {
        Node node = getNode(root, key);
        if (node == null)
            throw new IllegalArgumentException(key + " doesn't exist in the BST.");

        node.value = newValue;
    }

    public Node minimum(Node node) {
        if (node.left == null)
            return node;
        return minimum(node.left);
    }

    public V remove(K key) {
        Node node = getNode(root, key);
        if (node != null) {
            root = remove(root, key);
            return node.value;
        }
        return null;
    }

    private Node remove(Node node, K key) {
        if (node == null)
            return null;

        if (key.compareTo(node.key) < 0) {
            node.left = remove(node.left, key);
            return node;
        } else if (key.compareTo(node.key) > 0) {
            node.right = remove(node.right, key);
            return node;
        } else {
            //key.compareTo(node.key) == 0
            if (node.left == null) {
                Node rightNode = node.right;
                node.right = null;
                size--;
                return rightNode;
            }

            if (node.right == null) {
                Node leftNode = node.left;
                node.left = null;
                size--;
                return leftNode;
            }

            Node successor = minimum(node.right);
            successor.right = remove(node.right, successor.key);
            successor.left = node.left;

            node.left = node.right = null;

            return successor;
        }
    }
}

红黑树应用示例

以下是一个使用红黑树实现有序集合的示例代码:

public class TreeSet<E extends Comparable<E>> implements Set<E> {
    private RedBlackTree<E, Object> tree;

    public TreeSet() {
        tree = new RedBlackTree<>();
    }

    public int size() {
        return tree.getSize();
    }

    public boolean isEmpty() {
        return tree.isEmpty();
    }

    public boolean contains(Object o) {
        return tree.contains((E)o);
    }

    public boolean add(E e) {
        Object obj = tree.add(e, null);
        return obj == null;
    }

    public boolean remove(Object o) {
        Object obj = tree.remove((E)o);
        return obj != null;
    }

    public void clear() {
        tree = new RedBlackTree<>();
    }

    public Iterator<E> iterator() {
        return new TreeSetIterator(tree);
    }

    private class TreeSetIterator implements Iterator<E> {
        private Iterator<RedBlackTree.Node> iterator;

        public TreeSetIterator(RedBlackTree<E, Object> tree) {
            iterator = new RedBlackTreeIterator(tree);
        }

        public boolean hasNext() {
            return iterator.hasNext();
        }

        public E next() {
            RedBlackTree.Node node = iterator.next();
            return (E)node.key;
        }

        public void remove() {
            iterator.remove();
        }
    }

    private class RedBlackTreeIterator implements Iterator<RedBlackTree.Node> {
        private Stack<RedBlackTree.Node> stack;

        public RedBlackTreeIterator(RedBlackTree<E, Object> tree) {
            stack = new Stack<>();

            RedBlackTree.Node cur = tree.getRoot();
            while (cur != null) {
                stack.push(cur);
                cur = cur.left;
            }
        }

        public boolean hasNext() {
            return !stack.isEmpty();
        }

        public RedBlackTree.Node next() {
            RedBlackTree.Node cur = stack.pop();

            if (cur.right != null) {
                RedBlackTree.Node right = cur.right;
                while (right != null) {
                    stack.push(right);
                    right = right.left;
                }
            }

            return cur;
        }

        public void remove() {
            throw new UnsupportedOperationException();
        }
    }
}

该示例代码实现了一个基于红黑树实现的有序集合。其中,set 的基本操作都可以在 $O(\log(n))$ 的时间内完成。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java红黑树的数据结构与算法解析 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • 带你了解Java数据结构和算法之数组

    带你了解Java数据结构和算法之数组 在本教程中,我们将学习Java中的数组数据结构和对应的算法。让我们先来了解什么是数组。 什么是数组? 数组是一个同类型数据元素的集合,在内存中连续存储。数组具有索引性,我们可以使用索引值来访问数组中的元素。 声明和初始化数组 在Java中,声明一个数组需要指定以下三个参数: 数组的类型 数组的名称 数组的大小 以下是一个…

    数据结构 2023年5月17日
    00
  • mysql的Buffer Pool存储及原理解析

    下面我就来详细讲解一下“mysql的Buffer Pool存储及原理解析”的攻略。 Buffer Pool简介 在MySQL中,Buffer Pool是一个重要的概念,也可以说是MySQL最重要的性能优化建议之一。Buffer Pool是MySQL内存中缓存数据页的数据结构,用于加速数据的读写。 数据页 在MySQL中,数据是以数据页(page)为单位进行读…

    数据结构 2023年5月17日
    00
  • mosn基于延迟负载均衡算法 — 走得更快,期待走得更稳

    前言 这篇文章主要是介绍mosn在v1.5.0中新引入的基于延迟的负载均衡算法。 对分布式系统中延迟出现的原因进行剖析 介绍mosn都通过哪些方法来降低延迟 构建来与生产环境性能分布相近的测试用例来对算法进行验证 地址:https://github.com/mosn/mosn/pull/2253 在开始聊基于延迟的负载均衡算法之前,先介绍下什么是负载均衡——…

    算法与数据结构 2023年5月8日
    00
  • JavaScript数据结构和算法之二叉树详解

    JavaScript数据结构和算法之二叉树详解 什么是二叉树? 二叉树是一种树形结构,其中每个节点最多有两个子节点:左子节点和右子节点。每个节点都是一个对象,包括属性和方法。节点的属性可能包括值,左节点和右节点。节点的方法可能包括插入和删除。 二叉树的应用场景 二叉树的常用场景包括: 排序算法(二叉排序树); 表达式求值; 线段树; 图形图像学; 数据压缩算…

    数据结构 2023年5月17日
    00
  • 「分治」黑白棋子的移动

    本题为3月23日23上半学期集训每日一题中A题的题解 题面 题目描述 有2n个棋子(n≥4)排成一行,开始位置为白子全部在左边,黑子全部在右边,如下图为n=5的情形: ○○○○○●●●●● 移动棋子的规则是:每次必须同时移动相邻的两个棋子,颜色不限,可以左移也可以右移到空位上去,但不能调换两个棋子的左右位置。每次移动必须跳过若干个棋子(不能平移),要求最后能…

    算法与数据结构 2023年4月18日
    00
  • Python数据结构与算法之链表定义与用法实例详解【单链表、循环链表】

    Python数据结构与算法之链表定义与用法实例详解 什么是链表? 链表是一种常见的数据结构,它由一个个的节点组成,每个节点包含两部分,一部分存储数据,一部分存储下一个节点在哪里的指针。通过节点之间的指针,就可以将节点串起来,形成一个链表。 链表和数组是两种截然不同的数据结构,数组的元素在内存中是连续存储的,而链表的节点却可以分散在内存的不同位置,这也是链表灵…

    数据结构 2023年5月17日
    00
  • C#数据结构之单链表(LinkList)实例详解

    C#数据结构之单链表(LinkList)实例详解 概述 单链表是一种简单的数据结构,它由一些节点组成,每个节点包含着一个数据元素和一个指向下一个节点的指针。它的特点是可以快速的插入和删除节点,但在查找元素时效率不高。本篇文章将详细讲解单链表的实现过程和相关细节。 实现步骤 定义节点类 首先需要定义一个单链表节点类,包含两个部分:数据和指向下一个节点的指针。代…

    数据结构 2023年5月17日
    00
  • C++数据结构与算法的基础知识和经典算法汇总

    C++数据结构与算法的基础知识和经典算法汇总 1. 基础知识 1.1 数据结构 数据结构是计算机存储、组织数据的方式。这里列出常见的数据结构,包括但不限于: 数组 链表 栈 队列 树 哈希表 1.2 算法 算法是解决问题的步骤和方法。下列是常见的算法: 排序算法 查找算法 字符串算法 图算法 1.3 复杂度 复杂度是算法性能的度量。常见的复杂度表示法有O(n…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部