红黑树是一种自平衡的二叉查找树,是在普通的二叉查找树的基础上增加了一些限制和规则,使得它能够自我调整来保持平衡。它的作用主要有以下几个方面:
查找和插入元素的时间复杂度都是O(logN),其中N为树中节点的个数,因此红黑树可以高效地进行查找和插入操作。
在很多需要动态维护有序序列数据结构的场景中,红黑树可以非常高效地实现这个目标。
红黑树还可以用于高效地实现区间查询等数据结构,比如线段树。在这种场景下,红黑树作为线段树的底层数据结构,能够提升线段树查询、更新的效率。
总之,红黑树是一种非常有用的数据结构,其自平衡特性使得它具有高效的查找和插入等操作,因此被广泛应用于数据处理和算法实现的领域。
左旋是将当前节点往左旋转的操作。具体步骤如下:
- 将当前节点的右子节点(称为y)设为当前节点(称为x)的父节点。
- 将y的左子节点设为x的右子节点。
- 如果y的左子节点非空,将x设为y的左子节点的父节点。
- 将y的左子节点设为x。
- 将y的父节点设为原本x的父节点。
- 如果原本x的父节点为空,则将y设为红黑树的根节点;否则,如果x是其父节点的左子节点,则将y设为其父节点的左子节点;否则,将y设为其父节点的右子节点。
左旋是将当前节点往左旋转的操作。具体步骤如下:
- 将当前节点的右子节点(称为y)设为当前节点(称为x)的父节点。
- 将y的左子节点设为x的右子节点。
- 如果y的左子节点非空,将x设为y的左子节点的父节点。
- 将y的左子节点设为x。
- 将y的父节点设为原本x的父节点。
- 如果原本x的父节点为空,则将y设为红黑树的根节点;否则,如果x是其父节点的左子节点,则将y设为其父节点的左子节点;否则,将y设为其父节点的右子节点。
左右旋的作用:
通过左旋和右旋操作可以改变节点之间的位置关系,从而保持红黑树的平衡性。这两个操作在插入或删除节点时经常被用到,以确保红黑树的性质得到维护和恢复。
插入操作:
- 首先根据传入的键值创建一个新节点,并将其颜色设置为红色。
- 通过比较键值大小,将新节点插入到正确的位置上,确保满足二叉查找树的性质。
- 调用修复插入操作来保证红黑树的性质:
- 如果插入节点的父节点是黑色节点,那么不需要进行调整,红黑树的性质没有被破坏。
- 如果插入节点的父节点是红色节点,那么可能会破坏红黑树的性质,需要进行相应的调整。
修复插入操作: 在红黑树中,有三种情况需要进行调整,分别是:插入节点的父节点是红色的情况下,叔节点是红色的情况下,和插入节点的父节点是红色且叔节点是黑色的情况下。调整的目标是使得插入节点的父节点是黑色,叔节点和祖父节点是红色,保持红黑树的性质。
- 左旋转和右旋转:通过旋转操作来调整节点的位置,使得红黑树保持平衡。
- 颜色翻转:通过改变节点的颜色来维护红黑树的性质。
插入操作:
- 首先根据传入的键值创建一个新节点,并将其颜色设置为红色。
- 通过比较键值大小,将新节点插入到正确的位置上,确保满足二叉查找树的性质。
- 调用修复插入操作来保证红黑树的性质:
- 如果插入节点的父节点是黑色节点,那么不需要进行调整,红黑树的性质没有被破坏。
- 如果插入节点的父节点是红色节点,那么可能会破坏红黑树的性质,需要进行相应的调整。
修复删除操作: 删除节点可能会破坏红黑树的性质,需要进行相应的调整。
- 如果删除的节点是红色的,不会影响红黑树的性质,直接删除即可。
- 如果删除的节点是黑色的,可能会导致红黑树的性质被破坏,需要进行相应的修复。修复的目标是保持每个节点到其后代叶节点的黑色节点数量相同。
- // 红黑树节点类
- class RBNode {
- int data;
- RBNode parent;
- RBNode left;
- RBNode right;
- int color;
-
- public RBNode(int data) {
- this.data = data;
- this.parent = null;
- this.left = null;
- this.right = null;
- this.color = 1; // 默认节点为红色
- }
- }
- // 红黑树类
- class RedBlackTree {
- private RBNode root;
-
- public RedBlackTree() {
- root = null;
- }
- }
- // 左旋操作
- private void leftRotate(RBNode x) {
- RBNode y = x.right;
- x.right = y.left;
- if (y.left != null) {
- y.left.parent = x;
- }
- y.parent = x.parent;
- if (x.parent == null) {
- root = y;
- } else if (x == x.parent.left) {
- x.parent.left = y;
- } else {
- x.parent.right = y;
- }
- y.left = x;
- x.parent = y;
- }
- // 右旋操作
- private void rightRotate(RBNode y) {
- RBNode x = y.left;
- y.left = x.right;
- if (x.right != null) {
- x.right.parent = y;
- }
- x.parent = y.parent;
- if (y.parent == null) {
- root = x;
- } else if (y == y.parent.left) {
- y.parent.left = x;
- } else {
- y.parent.right = x;
- }
- x.right = y;
- y.parent = x;
- }
- // 插入节点
- public void insert(int key) {
- RBNode newNode = new RBNode(key);
- RBNode current = root;
- RBNode parent = null;
-
- while (current != null) {
- parent = current;
- if (key < current.data) {
- current = current.left;
- } else {
- current = current.right;
- }
- }
-
- newNode.parent = parent;
- if (parent == null) {
- root = newNode;
- } else if (key < parent.data) {
- parent.left = newNode;
- } else {
- parent.right = newNode;
- }
-
- // 调整红黑树
- fixInsert(newNode);
- }
- // 插入后修正红黑树平衡性
- private void fixInsert(RBNode node) {
- while (node.parent != null && node.parent.color == 1) {
- // 当前节点的父节点是祖父节点的左子节点
- if (node.parent == node.parent.parent.left) {
- RBNode uncle = node.parent.parent.right;
- // Case 1: 叔叔节点是红色
- if (uncle != null && uncle.color == 1) {
- node.parent.color = 0;
- uncle.color = 0;
- node.parent.parent.color = 1;
- node = node.parent.parent;
- } else {
- // Case 2: 叔叔节点是黑色,且当前节点是右子节点
- if (node == node.parent.right) {
- node = node.parent;
- leftRotate(node);
- }
- // Case 3: 叔叔节点是黑色,且当前节点是左子节点
- node.parent.color = 0;
- node.parent.parent.color = 1;
- rightRotate(node.parent.parent);
- }
- } else {
- // 当前节点的父节点是祖父节点的右子节点
- RBNode uncle = node.parent.parent.left;
- // Case 1: 叔叔节点是红色
- if (uncle != null && uncle.color == 1) {
- node.parent.color = 0;
- uncle.color = 0;
- node.parent.parent.color = 1;
- node = node.parent.parent;
- } else {
- // Case 2: 叔叔节点是黑色,且当前节点是左子节点
- if (node == node.parent.left) {
- node = node.parent;
- rightRotate(node);
- }
- // Case 3: 叔叔节点是黑色,且当前节点是右子节点
- node.parent.color = 0;
- node.parent.parent.color = 1;
- leftRotate(node.parent.parent);
- }
- }
- }
- root.color = 0;
- }
- // 删除节点
- public void delete(int key) {
- RBNode z = search(key);
- if (z == null) {
- return;
- }
-
- RBNode x, y;
- if (z.left == null || z.right == null) {
- y = z;
- } else {
- y = successor(z);
- }
-
- if (y.left != null) {
- x = y.left;
- } else {
- x = y.right;
- }
-
- if (x != null) {
- x.parent = y.parent;
- }
-
- if (y.parent == null) {
- root = x;
- } else if (y == y.parent.left) {
- y.parent.left = x;
- } else {
- y.parent.right = x;
- }
-
- if (y != z) {
- z.data = y.data;
- }
-
- if (y.color == 0) {
- fixDelete(x);
- }
- }
-
-
-
- // 查找节点
- public RBNode search(int key) {
- RBNode current = root;
- while (current != null && current.data != key) {
- if (key < current.data) {
- current = current.left;
- } else {
- current = current.right;
- }
- }
- return current;
- }
-
- // 查找后继节点
- private RBNode successor(RBNode x) {
- if (x.right != null) {
- RBNode current = x.right;
- while (current.left != null) {
- current = current.left;
- }
- return current;
- } else {
- RBNode y = x.parent;
- while (y != null && x == y.right) {
- x = y;
- y = y.parent;
- }
- return y;
- }
- }
- // 删除节点后修正红黑树平衡性
- private void fixDelete(RBNode node) {
- while (node != root && node.color == 0) {
- if (node == node.parent.left) {
- RBNode brother = node.parent.right;
- if (brother.color == 1) {
- brother.color = 0;
- node.parent.color = 1;
- leftRotate(node.parent);
- brother = node.parent.right;
- }
- if (brother.left.color == 0 && brother.right.color == 0) {
- brother.color = 1;
- node = node.parent;
- } else {
- if (brother.right.color == 0) {
- brother.left.color = 0;
- brother.color = 1;
- rightRotate(brother);
- brother = node.parent.right;
- }
- brother.color = node.parent.color;
- node.parent.color = 0;
- brother.right.color = 0;
- leftRotate(node.parent);
- node = root;
- }
- } else {
- RBNode brother = node.parent.left;
- if (brother.color == 1) {
- brother.color = 0;
- node.parent.color = 1;
- rightRotate(node.parent);
- brother = node.parent.left;
- }
- if (brother.right.color == 0 && brother.left.color == 0) {
- brother.color = 1;
- node = node.parent;
- } else {
- if (brother.left.color == 0) {
- brother.right.color = 0;
- brother.color = 1;
- leftRotate(brother);
- brother = node.parent.left;
- }
- brother.color = node.parent.color;
- node.parent.color = 0;
- brother.left.color = 0;
- rightRotate(node.parent);
- node = root;
- }
- }
- }
- node.color = 0;
- }
- // 红黑树节点类
- class RBNode {
- int data;
- RBNode parent;
- RBNode left;
- RBNode right;
- int color;
-
- public RBNode(int data) {
- this.data = data;
- this.parent = null;
- this.left = null;
- this.right = null;
- this.color = 1; // 默认节点为红色
- }
- }
-
- // 红黑树类
- class RedBlackTree {
- private RBNode root;
-
- public RedBlackTree() {
- root = null;
- }
-
- // 左旋操作
- private void leftRotate(RBNode x) {
- RBNode y = x.right;
- x.right = y.left;
- if (y.left != null) {
- y.left.parent = x;
- }
- y.parent = x.parent;
- if (x.parent == null) {
- root = y;
- } else if (x == x.parent.left) {
- x.parent.left = y;
- } else {
- x.parent.right = y;
- }
- y.left = x;
- x.parent = y;
- }
-
- // 右旋操作
- private void rightRotate(RBNode y) {
- RBNode x = y.left;
- y.left = x.right;
- if (x.right != null) {
- x.right.parent = y;
- }
- x.parent = y.parent;
- if (y.parent == null) {
- root = x;
- } else if (y == y.parent.left) {
- y.parent.left = x;
- } else {
- y.parent.right = x;
- }
- x.right = y;
- y.parent = x;
- }
-
- // 插入节点
- public void insert(int key) {
- RBNode newNode = new RBNode(key);
- RBNode current = root;
- RBNode parent = null;
-
- while (current != null) {
- parent = current;
- if (key < current.data) {
- current = current.left;
- } else {
- current = current.right;
- }
- }
-
- newNode.parent = parent;
- if (parent == null) {
- root = newNode;
- } else if (key < parent.data) {
- parent.left = newNode;
- } else {
- parent.right = newNode;
- }
-
- // 调整红黑树
- fixInsert(newNode);
- }
-
- // 插入后修正红黑树平衡性
- private void fixInsert(RBNode node) {
- while (node.parent != null && node.parent.color == 1) {
- // 当前节点的父节点是祖父节点的左子节点
- if (node.parent == node.parent.parent.left) {
- RBNode uncle = node.parent.parent.right;
- // Case 1: 叔叔节点是红色
- if (uncle != null && uncle.color == 1) {
- node.parent.color = 0;
- uncle.color = 0;
- node.parent.parent.color = 1;
- node = node.parent.parent;
- } else {
- // Case 2: 叔叔节点是黑色,且当前节点是右子节点
- if (node == node.parent.right) {
- node = node.parent;
- leftRotate(node);
- }
- // Case 3: 叔叔节点是黑色,且当前节点是左子节点
- node.parent.color = 0;
- node.parent.parent.color = 1;
- rightRotate(node.parent.parent);
- }
- } else {
- // 当前节点的父节点是祖父节点的右子节点
- RBNode uncle = node.parent.parent.left;
- // Case 1: 叔叔节点是红色
- if (uncle != null && uncle.color == 1) {
- node.parent.color = 0;
- uncle.color = 0;
- node.parent.parent.color = 1;
- node = node.parent.parent;
- } else {
- // Case 2: 叔叔节点是黑色,且当前节点是左子节点
- if (node == node.parent.left) {
- node = node.parent;
- rightRotate(node);
- }
- // Case 3: 叔叔节点是黑色,且当前节点是右子节点
- node.parent.color = 0;
- node.parent.parent.color = 1;
- leftRotate(node.parent.parent);
- }
- }
- }
- root.color = 0;
- }
-
- // 删除节点
- public void delete(int key) {
- RBNode z = search(key);
- if (z == null) {
- return;
- }
-
- RBNode x, y;
- if (z.left == null || z.right == null) {
- y = z;
- } else {
- y = successor(z);
- }
-
- if (y.left != null) {
- x = y.left;
- } else {
- x = y.right;
- }
-
- if (x != null) {
- x.parent = y.parent;
- }
-
- if (y.parent == null) {
- root = x;
- } else if (y == y.parent.left) {
- y.parent.left = x;
- } else {
- y.parent.right = x;
- }
-
- if (y != z) {
- z.data = y.data;
- }
-
- if (y.color == 0) {
- fixDelete(x);
- }
- }
-
- // 删除节点后修正红黑树平衡性
- private void fixDelete(RBNode node) {
- while (node != root && node.color == 0) {
- if (node == node.parent.left) {
- RBNode brother = node.parent.right;
- if (brother.color == 1) {
- brother.color = 0;
- node.parent.color = 1;
- leftRotate(node.parent);
- brother = node.parent.right;
- }
- if (brother.left.color == 0 && brother.right.color == 0) {
- brother.color = 1;
- node = node.parent;
- } else {
- if (brother.right.color == 0) {
- brother.left.color = 0;
- brother.color = 1;
- rightRotate(brother);
- brother = node.parent.right;
- }
- brother.color = node.parent.color;
- node.parent.color = 0;
- brother.right.color = 0;
- leftRotate(node.parent);
- node = root;
- }
- } else {
- RBNode brother = node.parent.left;
- if (brother.color == 1) {
- brother.color = 0;
- node.parent.color = 1;
- rightRotate(node.parent);
- brother = node.parent.left;
- }
- if (brother.right.color == 0 && brother.left.color == 0) {
- brother.color = 1;
- node = node.parent;
- } else {
- if (brother.left.color == 0) {
- brother.right.color = 0;
- brother.color = 1;
- leftRotate(brother);
- brother = node.parent.left;
- }
- brother.color = node.parent.color;
- node.parent.color = 0;
- brother.left.color = 0;
- rightRotate(node.parent);
- node = root;
- }
- }
- }
- node.color = 0;
- }
-
- // 查找节点
- public RBNode search(int key) {
- RBNode current = root;
- while (current != null && current.data != key) {
- if (key < current.data) {
- current = current.left;
- } else {
- current = current.right;
- }
- }
- return current;
- }
-
- // 查找后继节点
- private RBNode successor(RBNode x) {
- if (x.right != null) {
- RBNode current = x.right;
- while (current.left != null) {
- current = current.left;
- }
- return current;
- } else {
- RBNode y = x.parent;
- while (y != null && x == y.right) {
- x = y;
- y = y.parent;
- }
- return y;
- }
- }
-
- // 修改节点
- public void modify(int oldKey, int newKey) {
- RBNode node = search(oldKey);
- if (node != null) {
- delete(oldKey);
- insert(newKey);
- }
- }
-
-
- // 中序遍历红黑树
- private void inorderTraversal(RBNode node) {
- if (node != null) {
- inorderTraversal(node.left);
- System.out.print(node.data + " ");
- inorderTraversal(node.right);
- }
- }
-
- public void printTree() {
- inorderTraversal(root);
- }
- }
-
-
- public class Main {
- public static void main(String[] args) {
- RedBlackTree tree = new RedBlackTree();
- tree.insert(10);
- tree.insert(15);
- tree.insert(13);
- tree.insert(16);
- tree.insert(5);
- tree.insert(7);
-
- System.out.println("红黑树中序遍历结果:");
- tree.printTree();
- }
- }