数据结构:红黑树

文章目录

  • 红黑数
    • 一,概述
    • 二,添加数据
    • 三,删除数据


红黑数

一,概述

红黑树是一种自平衡二叉查找树,它在二叉搜索树中增加了节点颜色限制(红/黑)和规则约定(最长路径中的节点个数不超过最短路径中节点个数的2倍),从而确保树接近平衡。红黑树的应用相当广泛,主要是用它来存储有序的数据,它的时间复杂度为O(logn),查询效率非常高。

红黑树具有以下性质:

  1. 每个节点不是黑色就是红色。
  2. 根节点是黑色。
  3. 如果有一个节点是红色的,则它的两个孩子节点必定是黑色。
  4. 从该节点到其它所有后代叶节点的路径上,均包含相同数据的黑色节点,每条路径中的黑色节点数量相同。
  5. 每个空指针域都是黑色。

红黑树和AVL树的区别在于,红黑树并不追求“完全平衡”——它只要求部分地达到平衡要求,降低了对旋转的要求,从而提高了性能。红黑树的时间复杂度和AVL树相同,但统计性能比AVL树更高。任何不平衡都会在三次旋转之内解决。红黑树能够以O(log2 n)的时间复杂度进行搜索、插入、删除操作。

简介

  • 红黑树是一种自平衡的二叉搜索树,它通过对节点进行颜色标记和旋转操作来维护树的平衡。
  • 红黑树的节点分为红色和黑色两种颜色,根节点总是黑色的,每个叶子节点(NIL节点,空节点)都是黑色的。
  • 红黑树满足以下5个性质:
    1. 每个节点要么是红色的,要么是黑色的。
    2. 根节点是黑色的。
    3. 每个叶子节点都是黑色的空节点(NIL节点)。
    4. 如果一个节点是红色的,则它的两个子节点都是黑色的。
    5. 对于每个节点,从该节点到其所有后代叶子节点的简单路径上,均包含相同数量的黑色节点。

图示

以下是一个简单的红黑树示例:

        (黑色) 8
       /      \
     (黑色)  10   (红色)
    /  \       \
  (红色) 3    12   (黑色)
 /        \
2          (红色) 6
          /      \
        (红色)   4   (黑色)

在这个示例中,节点中的数字表示节点的值,括号中的颜色表示节点的颜色。根节点是黑色的,叶子节点是黑色的空节点,每个红色节点的两个子节点都是黑色的,从每个节点到其后代叶子节点的简单路径上包含相同数量的黑色节点。

示例

以下是一个Java实现的简单红黑树示例:

public class RedBlackTree<T extends Comparable<T>> {
    private static final boolean RED = true;
    private static final boolean BLACK = false;
    private class Node {
        T key;
        Node left;
        Node right;
        boolean color;
        Node(T key, boolean color) {
            this.key = key;
            this.color = color;
        }
    }
    private Node root;
    private void insert(Node node, T key) {
        if (node == null) {
            node = new Node(key, RED);
        } else if (key.compareTo(node.key) < 0) {
            insert(node.left, key);
            if (node.left.color == RED) {
                node = rotateRight(node);
            }
        } else if (key.compareTo(node.key) > 0) {
            insert(node.right, key);
            if (node.right.color == RED) {
                node = rotateLeft(node);
            }
        } else { // Duplicate keys not allowed
            return;
        }
        node.color = BLACK;
    }
    private Node rotateLeft(Node node) {
        // Perform left rotation on the given node
    }
    private Node rotateRight(Node node) {
        // Perform right rotation on the given node
    }
    public void add(T key) {
        root = insert(root, key);
        root.color = BLACK; // Ensure root is always black
    }
    // Other methods for searching, deleting, and traversing the tree
}

在这个示例中,定义了一个红黑树类,其中包含一个内部类Node,用于表示红黑树的节点。节点包含一个键、一个左子节点、一个右子节点和一个颜色属性。红黑树类还包含一个根节点,以及插入、左旋、右旋和添加方法。在插入方法中,检查要插入的节点是否为空,如果为空,则创建一个新节点并将其颜色设置为红色。如果键小于当前节点的键,将其插入到左子树中,如果左子树是红色的,则对当前节点进行右旋。如果键大于当前节点的键,将其插入到右子树中,如果右子树是红色的,则对当前节点进行左旋。最后,将当前节点的颜色设置为黑色。在左旋和右旋方法中,需要实现红黑树的旋转操作。

二,添加数据

红黑树是一种自平衡二叉查找树,它在插入和删除元素时可以自动保持平衡。在Java中,可以使用TreeMap类来实现红黑树。以下是如何使用TreeMap来添加数据的示例:

import java.util.TreeMap;

public class Main {
    public static void main(String[] args) {
        // 创建一个新的TreeMap实例
        TreeMap<Integer, String> treeMap = new TreeMap<>();

        // 向TreeMap中添加数据
        treeMap.put(1, "One");
        treeMap.put(2, "Two");
        treeMap.put(3, "Three");

        // 输出TreeMap的内容
        for (Map.Entry<Integer, String> entry : treeMap.entrySet()) {
            System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
        }
    }
}

这个例子中,首先创建了一个新的TreeMap实例。然后,使用put()方法向TreeMap中添加数据。最后,遍历并打印出TreeMap的内容。

需要注意的是,TreeMap的键(key)必须是可排序的。在上面的例子中,使用的键是Integer,这是可排序的。当试图添加一个不可排序的键时,Java编译器会报错。

三,删除数据

红黑树是一种自平衡二叉查找树,它在插入和删除元素时可以自动保持平衡。在Java中,可以使用TreeMap类来实现红黑树。以下是如何使用TreeMap来删除数据的示例:

import java.util.TreeMap;

public class Main {
    public static void main(String[] args) {
        // 创建一个新的TreeMap实例
        TreeMap<Integer, String> treeMap = new TreeMap<>();

        // 向TreeMap中添加数据
        treeMap.put(1, "One");
        treeMap.put(2, "Two");
        treeMap.put(3, "Three");

        // 输出TreeMap的内容
        System.out.println("Before deletion: " + treeMap);

        // 删除键为2的元素
        treeMap.remove(2);

        // 输出TreeMap的内容
        System.out.println("After deletion: " + treeMap);
    }
}

这个例子中,首先创建了一个新的TreeMap实例,并添加了一些数据。然后,使用remove()方法删除了键为2的元素。最后,打印出删除前后的TreeMap的内容。

需要注意的是,TreeMap的键(key)必须是可排序的。在上面的例子中,使用的键是Integer,这是可排序的。当试图添加一个不可排序的键时,Java编译器会报错。

你可能感兴趣的:(数据结构,学习笔记,数据结构,红黑树)