• 你真的了解红黑树的怎么实现的吗?


    1.前言

    红黑树是一种自平衡的二叉查找树,是在普通的二叉查找树的基础上增加了一些限制和规则,使得它能够自我调整来保持平衡。它的作用主要有以下几个方面:

    1. 查找和插入元素的时间复杂度都是O(logN),其中N为树中节点的个数,因此红黑树可以高效地进行查找和插入操作。

    2. 在很多需要动态维护有序序列数据结构的场景中,红黑树可以非常高效地实现这个目标。

    3. 红黑树还可以用于高效地实现区间查询等数据结构,比如线段树。在这种场景下,红黑树作为线段树的底层数据结构,能够提升线段树查询、更新的效率。

    总之,红黑树是一种非常有用的数据结构,其自平衡特性使得它具有高效的查找和插入等操作,因此被广泛应用于数据处理和算法实现的领域。 

     2.原理分析

    2.1.左旋操作

    左旋是将当前节点往左旋转的操作。具体步骤如下:

    1. 将当前节点的右子节点(称为y)设为当前节点(称为x)的父节点。
    2. 将y的左子节点设为x的右子节点。
    3. 如果y的左子节点非空,将x设为y的左子节点的父节点。
    4. 将y的左子节点设为x。
    5. 将y的父节点设为原本x的父节点。
    6. 如果原本x的父节点为空,则将y设为红黑树的根节点;否则,如果x是其父节点的左子节点,则将y设为其父节点的左子节点;否则,将y设为其父节点的右子节点。

    2.2右旋操作

    左旋是将当前节点往左旋转的操作。具体步骤如下:

    1. 将当前节点的右子节点(称为y)设为当前节点(称为x)的父节点。
    2. 将y的左子节点设为x的右子节点。
    3. 如果y的左子节点非空,将x设为y的左子节点的父节点。
    4. 将y的左子节点设为x。
    5. 将y的父节点设为原本x的父节点。
    6. 如果原本x的父节点为空,则将y设为红黑树的根节点;否则,如果x是其父节点的左子节点,则将y设为其父节点的左子节点;否则,将y设为其父节点的右子节点。

    左右旋的作用:

    通过左旋和右旋操作可以改变节点之间的位置关系,从而保持红黑树的平衡性。这两个操作在插入或删除节点时经常被用到,以确保红黑树的性质得到维护和恢复。

    2.3 插入节点

    1. 插入操作:

      • 首先根据传入的键值创建一个新节点,并将其颜色设置为红色。
      • 通过比较键值大小,将新节点插入到正确的位置上,确保满足二叉查找树的性质。
      • 调用修复插入操作来保证红黑树的性质:
        • 如果插入节点的父节点是黑色节点,那么不需要进行调整,红黑树的性质没有被破坏。
        • 如果插入节点的父节点是红色节点,那么可能会破坏红黑树的性质,需要进行相应的调整。

    2.4插入后维持红黑树的平衡性

    1. 修复插入操作: 在红黑树中,有三种情况需要进行调整,分别是:插入节点的父节点是红色的情况下,叔节点是红色的情况下,和插入节点的父节点是红色且叔节点是黑色的情况下。调整的目标是使得插入节点的父节点是黑色,叔节点和祖父节点是红色,保持红黑树的性质。

      • 左旋转和右旋转:通过旋转操作来调整节点的位置,使得红黑树保持平衡。
      • 颜色翻转:通过改变节点的颜色来维护红黑树的性质。

    2.5删除节点 

    1. 插入操作:

      • 首先根据传入的键值创建一个新节点,并将其颜色设置为红色。
      • 通过比较键值大小,将新节点插入到正确的位置上,确保满足二叉查找树的性质。
      • 调用修复插入操作来保证红黑树的性质:
        • 如果插入节点的父节点是黑色节点,那么不需要进行调整,红黑树的性质没有被破坏。
        • 如果插入节点的父节点是红色节点,那么可能会破坏红黑树的性质,需要进行相应的调整。

    2.6删除后维持红黑树的平衡性

    1. 修复删除操作: 删除节点可能会破坏红黑树的性质,需要进行相应的调整。

      • 如果删除的节点是红色的,不会影响红黑树的性质,直接删除即可。
      • 如果删除的节点是黑色的,可能会导致红黑树的性质被破坏,需要进行相应的修复。修复的目标是保持每个节点到其后代叶节点的黑色节点数量相同。

    3.代码实现

    3.1准备工作

    1. // 红黑树节点类
    2. class RBNode {
    3. int data;
    4. RBNode parent;
    5. RBNode left;
    6. RBNode right;
    7. int color;
    8. public RBNode(int data) {
    9. this.data = data;
    10. this.parent = null;
    11. this.left = null;
    12. this.right = null;
    13. this.color = 1; // 默认节点为红色
    14. }
    15. }
    16. // 红黑树类
    17. class RedBlackTree {
    18. private RBNode root;
    19. public RedBlackTree() {
    20. root = null;
    21. }
    22. }

    3.2.左旋操作

    1. // 左旋操作
    2. private void leftRotate(RBNode x) {
    3. RBNode y = x.right;
    4. x.right = y.left;
    5. if (y.left != null) {
    6. y.left.parent = x;
    7. }
    8. y.parent = x.parent;
    9. if (x.parent == null) {
    10. root = y;
    11. } else if (x == x.parent.left) {
    12. x.parent.left = y;
    13. } else {
    14. x.parent.right = y;
    15. }
    16. y.left = x;
    17. x.parent = y;
    18. }

    3.3右旋操作

    1. // 右旋操作
    2. private void rightRotate(RBNode y) {
    3. RBNode x = y.left;
    4. y.left = x.right;
    5. if (x.right != null) {
    6. x.right.parent = y;
    7. }
    8. x.parent = y.parent;
    9. if (y.parent == null) {
    10. root = x;
    11. } else if (y == y.parent.left) {
    12. y.parent.left = x;
    13. } else {
    14. y.parent.right = x;
    15. }
    16. x.right = y;
    17. y.parent = x;
    18. }

    3.4插入节点

    1. // 插入节点
    2. public void insert(int key) {
    3. RBNode newNode = new RBNode(key);
    4. RBNode current = root;
    5. RBNode parent = null;
    6. while (current != null) {
    7. parent = current;
    8. if (key < current.data) {
    9. current = current.left;
    10. } else {
    11. current = current.right;
    12. }
    13. }
    14. newNode.parent = parent;
    15. if (parent == null) {
    16. root = newNode;
    17. } else if (key < parent.data) {
    18. parent.left = newNode;
    19. } else {
    20. parent.right = newNode;
    21. }
    22. // 调整红黑树
    23. fixInsert(newNode);
    24. }

    3.5插入后维持红黑树的平衡性

    1. // 插入后修正红黑树平衡性
    2. private void fixInsert(RBNode node) {
    3. while (node.parent != null && node.parent.color == 1) {
    4. // 当前节点的父节点是祖父节点的左子节点
    5. if (node.parent == node.parent.parent.left) {
    6. RBNode uncle = node.parent.parent.right;
    7. // Case 1: 叔叔节点是红色
    8. if (uncle != null && uncle.color == 1) {
    9. node.parent.color = 0;
    10. uncle.color = 0;
    11. node.parent.parent.color = 1;
    12. node = node.parent.parent;
    13. } else {
    14. // Case 2: 叔叔节点是黑色,且当前节点是右子节点
    15. if (node == node.parent.right) {
    16. node = node.parent;
    17. leftRotate(node);
    18. }
    19. // Case 3: 叔叔节点是黑色,且当前节点是左子节点
    20. node.parent.color = 0;
    21. node.parent.parent.color = 1;
    22. rightRotate(node.parent.parent);
    23. }
    24. } else {
    25. // 当前节点的父节点是祖父节点的右子节点
    26. RBNode uncle = node.parent.parent.left;
    27. // Case 1: 叔叔节点是红色
    28. if (uncle != null && uncle.color == 1) {
    29. node.parent.color = 0;
    30. uncle.color = 0;
    31. node.parent.parent.color = 1;
    32. node = node.parent.parent;
    33. } else {
    34. // Case 2: 叔叔节点是黑色,且当前节点是左子节点
    35. if (node == node.parent.left) {
    36. node = node.parent;
    37. rightRotate(node);
    38. }
    39. // Case 3: 叔叔节点是黑色,且当前节点是右子节点
    40. node.parent.color = 0;
    41. node.parent.parent.color = 1;
    42. leftRotate(node.parent.parent);
    43. }
    44. }
    45. }
    46. root.color = 0;
    47. }

    3.6删除节点

    1. // 删除节点
    2. public void delete(int key) {
    3. RBNode z = search(key);
    4. if (z == null) {
    5. return;
    6. }
    7. RBNode x, y;
    8. if (z.left == null || z.right == null) {
    9. y = z;
    10. } else {
    11. y = successor(z);
    12. }
    13. if (y.left != null) {
    14. x = y.left;
    15. } else {
    16. x = y.right;
    17. }
    18. if (x != null) {
    19. x.parent = y.parent;
    20. }
    21. if (y.parent == null) {
    22. root = x;
    23. } else if (y == y.parent.left) {
    24. y.parent.left = x;
    25. } else {
    26. y.parent.right = x;
    27. }
    28. if (y != z) {
    29. z.data = y.data;
    30. }
    31. if (y.color == 0) {
    32. fixDelete(x);
    33. }
    34. }
    35. // 查找节点
    36. public RBNode search(int key) {
    37. RBNode current = root;
    38. while (current != null && current.data != key) {
    39. if (key < current.data) {
    40. current = current.left;
    41. } else {
    42. current = current.right;
    43. }
    44. }
    45. return current;
    46. }
    47. // 查找后继节点
    48. private RBNode successor(RBNode x) {
    49. if (x.right != null) {
    50. RBNode current = x.right;
    51. while (current.left != null) {
    52. current = current.left;
    53. }
    54. return current;
    55. } else {
    56. RBNode y = x.parent;
    57. while (y != null && x == y.right) {
    58. x = y;
    59. y = y.parent;
    60. }
    61. return y;
    62. }
    63. }

    3.7删除后维持红黑树的平衡性

    1. // 删除节点后修正红黑树平衡性
    2. private void fixDelete(RBNode node) {
    3. while (node != root && node.color == 0) {
    4. if (node == node.parent.left) {
    5. RBNode brother = node.parent.right;
    6. if (brother.color == 1) {
    7. brother.color = 0;
    8. node.parent.color = 1;
    9. leftRotate(node.parent);
    10. brother = node.parent.right;
    11. }
    12. if (brother.left.color == 0 && brother.right.color == 0) {
    13. brother.color = 1;
    14. node = node.parent;
    15. } else {
    16. if (brother.right.color == 0) {
    17. brother.left.color = 0;
    18. brother.color = 1;
    19. rightRotate(brother);
    20. brother = node.parent.right;
    21. }
    22. brother.color = node.parent.color;
    23. node.parent.color = 0;
    24. brother.right.color = 0;
    25. leftRotate(node.parent);
    26. node = root;
    27. }
    28. } else {
    29. RBNode brother = node.parent.left;
    30. if (brother.color == 1) {
    31. brother.color = 0;
    32. node.parent.color = 1;
    33. rightRotate(node.parent);
    34. brother = node.parent.left;
    35. }
    36. if (brother.right.color == 0 && brother.left.color == 0) {
    37. brother.color = 1;
    38. node = node.parent;
    39. } else {
    40. if (brother.left.color == 0) {
    41. brother.right.color = 0;
    42. brother.color = 1;
    43. leftRotate(brother);
    44. brother = node.parent.left;
    45. }
    46. brother.color = node.parent.color;
    47. node.parent.color = 0;
    48. brother.left.color = 0;
    49. rightRotate(node.parent);
    50. node = root;
    51. }
    52. }
    53. }
    54. node.color = 0;
    55. }

    4.完整代码

    1. // 红黑树节点类
    2. class RBNode {
    3. int data;
    4. RBNode parent;
    5. RBNode left;
    6. RBNode right;
    7. int color;
    8. public RBNode(int data) {
    9. this.data = data;
    10. this.parent = null;
    11. this.left = null;
    12. this.right = null;
    13. this.color = 1; // 默认节点为红色
    14. }
    15. }
    16. // 红黑树类
    17. class RedBlackTree {
    18. private RBNode root;
    19. public RedBlackTree() {
    20. root = null;
    21. }
    22. // 左旋操作
    23. private void leftRotate(RBNode x) {
    24. RBNode y = x.right;
    25. x.right = y.left;
    26. if (y.left != null) {
    27. y.left.parent = x;
    28. }
    29. y.parent = x.parent;
    30. if (x.parent == null) {
    31. root = y;
    32. } else if (x == x.parent.left) {
    33. x.parent.left = y;
    34. } else {
    35. x.parent.right = y;
    36. }
    37. y.left = x;
    38. x.parent = y;
    39. }
    40. // 右旋操作
    41. private void rightRotate(RBNode y) {
    42. RBNode x = y.left;
    43. y.left = x.right;
    44. if (x.right != null) {
    45. x.right.parent = y;
    46. }
    47. x.parent = y.parent;
    48. if (y.parent == null) {
    49. root = x;
    50. } else if (y == y.parent.left) {
    51. y.parent.left = x;
    52. } else {
    53. y.parent.right = x;
    54. }
    55. x.right = y;
    56. y.parent = x;
    57. }
    58. // 插入节点
    59. public void insert(int key) {
    60. RBNode newNode = new RBNode(key);
    61. RBNode current = root;
    62. RBNode parent = null;
    63. while (current != null) {
    64. parent = current;
    65. if (key < current.data) {
    66. current = current.left;
    67. } else {
    68. current = current.right;
    69. }
    70. }
    71. newNode.parent = parent;
    72. if (parent == null) {
    73. root = newNode;
    74. } else if (key < parent.data) {
    75. parent.left = newNode;
    76. } else {
    77. parent.right = newNode;
    78. }
    79. // 调整红黑树
    80. fixInsert(newNode);
    81. }
    82. // 插入后修正红黑树平衡性
    83. private void fixInsert(RBNode node) {
    84. while (node.parent != null && node.parent.color == 1) {
    85. // 当前节点的父节点是祖父节点的左子节点
    86. if (node.parent == node.parent.parent.left) {
    87. RBNode uncle = node.parent.parent.right;
    88. // Case 1: 叔叔节点是红色
    89. if (uncle != null && uncle.color == 1) {
    90. node.parent.color = 0;
    91. uncle.color = 0;
    92. node.parent.parent.color = 1;
    93. node = node.parent.parent;
    94. } else {
    95. // Case 2: 叔叔节点是黑色,且当前节点是右子节点
    96. if (node == node.parent.right) {
    97. node = node.parent;
    98. leftRotate(node);
    99. }
    100. // Case 3: 叔叔节点是黑色,且当前节点是左子节点
    101. node.parent.color = 0;
    102. node.parent.parent.color = 1;
    103. rightRotate(node.parent.parent);
    104. }
    105. } else {
    106. // 当前节点的父节点是祖父节点的右子节点
    107. RBNode uncle = node.parent.parent.left;
    108. // Case 1: 叔叔节点是红色
    109. if (uncle != null && uncle.color == 1) {
    110. node.parent.color = 0;
    111. uncle.color = 0;
    112. node.parent.parent.color = 1;
    113. node = node.parent.parent;
    114. } else {
    115. // Case 2: 叔叔节点是黑色,且当前节点是左子节点
    116. if (node == node.parent.left) {
    117. node = node.parent;
    118. rightRotate(node);
    119. }
    120. // Case 3: 叔叔节点是黑色,且当前节点是右子节点
    121. node.parent.color = 0;
    122. node.parent.parent.color = 1;
    123. leftRotate(node.parent.parent);
    124. }
    125. }
    126. }
    127. root.color = 0;
    128. }
    129. // 删除节点
    130. public void delete(int key) {
    131. RBNode z = search(key);
    132. if (z == null) {
    133. return;
    134. }
    135. RBNode x, y;
    136. if (z.left == null || z.right == null) {
    137. y = z;
    138. } else {
    139. y = successor(z);
    140. }
    141. if (y.left != null) {
    142. x = y.left;
    143. } else {
    144. x = y.right;
    145. }
    146. if (x != null) {
    147. x.parent = y.parent;
    148. }
    149. if (y.parent == null) {
    150. root = x;
    151. } else if (y == y.parent.left) {
    152. y.parent.left = x;
    153. } else {
    154. y.parent.right = x;
    155. }
    156. if (y != z) {
    157. z.data = y.data;
    158. }
    159. if (y.color == 0) {
    160. fixDelete(x);
    161. }
    162. }
    163. // 删除节点后修正红黑树平衡性
    164. private void fixDelete(RBNode node) {
    165. while (node != root && node.color == 0) {
    166. if (node == node.parent.left) {
    167. RBNode brother = node.parent.right;
    168. if (brother.color == 1) {
    169. brother.color = 0;
    170. node.parent.color = 1;
    171. leftRotate(node.parent);
    172. brother = node.parent.right;
    173. }
    174. if (brother.left.color == 0 && brother.right.color == 0) {
    175. brother.color = 1;
    176. node = node.parent;
    177. } else {
    178. if (brother.right.color == 0) {
    179. brother.left.color = 0;
    180. brother.color = 1;
    181. rightRotate(brother);
    182. brother = node.parent.right;
    183. }
    184. brother.color = node.parent.color;
    185. node.parent.color = 0;
    186. brother.right.color = 0;
    187. leftRotate(node.parent);
    188. node = root;
    189. }
    190. } else {
    191. RBNode brother = node.parent.left;
    192. if (brother.color == 1) {
    193. brother.color = 0;
    194. node.parent.color = 1;
    195. rightRotate(node.parent);
    196. brother = node.parent.left;
    197. }
    198. if (brother.right.color == 0 && brother.left.color == 0) {
    199. brother.color = 1;
    200. node = node.parent;
    201. } else {
    202. if (brother.left.color == 0) {
    203. brother.right.color = 0;
    204. brother.color = 1;
    205. leftRotate(brother);
    206. brother = node.parent.left;
    207. }
    208. brother.color = node.parent.color;
    209. node.parent.color = 0;
    210. brother.left.color = 0;
    211. rightRotate(node.parent);
    212. node = root;
    213. }
    214. }
    215. }
    216. node.color = 0;
    217. }
    218. // 查找节点
    219. public RBNode search(int key) {
    220. RBNode current = root;
    221. while (current != null && current.data != key) {
    222. if (key < current.data) {
    223. current = current.left;
    224. } else {
    225. current = current.right;
    226. }
    227. }
    228. return current;
    229. }
    230. // 查找后继节点
    231. private RBNode successor(RBNode x) {
    232. if (x.right != null) {
    233. RBNode current = x.right;
    234. while (current.left != null) {
    235. current = current.left;
    236. }
    237. return current;
    238. } else {
    239. RBNode y = x.parent;
    240. while (y != null && x == y.right) {
    241. x = y;
    242. y = y.parent;
    243. }
    244. return y;
    245. }
    246. }
    247. // 修改节点
    248. public void modify(int oldKey, int newKey) {
    249. RBNode node = search(oldKey);
    250. if (node != null) {
    251. delete(oldKey);
    252. insert(newKey);
    253. }
    254. }
    255. // 中序遍历红黑树
    256. private void inorderTraversal(RBNode node) {
    257. if (node != null) {
    258. inorderTraversal(node.left);
    259. System.out.print(node.data + " ");
    260. inorderTraversal(node.right);
    261. }
    262. }
    263. public void printTree() {
    264. inorderTraversal(root);
    265. }
    266. }
    267. public class Main {
    268. public static void main(String[] args) {
    269. RedBlackTree tree = new RedBlackTree();
    270. tree.insert(10);
    271. tree.insert(15);
    272. tree.insert(13);
    273. tree.insert(16);
    274. tree.insert(5);
    275. tree.insert(7);
    276. System.out.println("红黑树中序遍历结果:");
    277. tree.printTree();
    278. }
    279. }

  • 相关阅读:
    aspnetcore中aop的实现
    22年牛客网最全面的Java面试手册,助你金九银十轻松过关
    sql注入手法详解
    EffectiveC++-条款41:了解隐式接口和编译器多态
    点击化学修饰多肽:DBCO-PEG-YIGSR/RVG29/R8/CCK8肽
    入侵野草(IWO)优化算法(Matlab完整代码实现)
    精读大型网站架构:前端架构模块化的方法及困境,自研框架Trick
    双-(二苯胺基-苯基)-苯并[c]硫代咪唑聚集诱导发光微球/四苯基乙烯聚集诱导发光AIE微球
    Java每日笔试题错题分析(7)
    原型和原型链
  • 原文地址:https://blog.csdn.net/m0_74749208/article/details/133914499