Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

597 lines
15 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. redblack.c
  5. Abstract:
  6. This module implements red/black trees.
  7. Author:
  8. 16-Jun-1995 t-orig
  9. Revision History:
  10. --*/
  11. #include <nt.h>
  12. #include <ntrtl.h>
  13. #include <nturtl.h>
  14. #include <windows.h>
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include <stdarg.h>
  19. #include "gen.h"
  20. PKNOWNTYPES NIL;
  21. #define RIGHT(x) x->RBRight
  22. #define LEFT(x) x->RBLeft
  23. #define PARENT(x) x->RBParent
  24. #define COLOR(x) x->RBColor
  25. #define KEY(x) x->TypeName
  26. VOID
  27. RBInitTree(
  28. PRBTREE ptree
  29. )
  30. {
  31. ptree->pRoot = NIL;
  32. ptree->pLastNodeInserted = NULL;
  33. }
  34. PKNOWNTYPES
  35. RBLeftRotate(
  36. PKNOWNTYPES root,
  37. PKNOWNTYPES x
  38. )
  39. /*++
  40. Routine Description:
  41. Rotates the tree to the left at node x.
  42. x y
  43. / \ / \
  44. A y ==>> x C
  45. / \ / \
  46. B C A B
  47. Arguments:
  48. root - The root of the Red/Black tree
  49. x - The node at which to rotate
  50. Return Value:
  51. return-value - The new root of the tree (which could be the same as
  52. the old root).
  53. --*/
  54. {
  55. PKNOWNTYPES y;
  56. y = RIGHT(x);
  57. RIGHT(x) = LEFT(y);
  58. if (LEFT(y) != NIL){
  59. PARENT(LEFT(y)) = x;
  60. }
  61. PARENT(y) = PARENT(x);
  62. if (PARENT(x) == NIL){
  63. root = y;
  64. } else if (x==LEFT(PARENT(x))) {
  65. LEFT(PARENT(x)) = y;
  66. } else {
  67. RIGHT(PARENT(x))= y;
  68. }
  69. LEFT(y) = x;
  70. PARENT(x) = y;
  71. return root;
  72. }
  73. PKNOWNTYPES
  74. RBRightRotate(
  75. PKNOWNTYPES root,
  76. PKNOWNTYPES x
  77. )
  78. /*++
  79. Routine Description:
  80. Rotates the tree to the right at node x.
  81. x y
  82. / \ / \
  83. y C ==>> A x
  84. / \ / \
  85. A B B C
  86. Arguments:
  87. root - The root of the Red/Black tree
  88. x - The node at which to rotate
  89. Return Value:
  90. return-value - The new root of the tree (which could be the same as
  91. the old root).
  92. --*/
  93. {
  94. PKNOWNTYPES y;
  95. y = LEFT(x);
  96. LEFT(x) = RIGHT(y);
  97. if (RIGHT(y) != NIL) {
  98. PARENT(RIGHT(y)) = x;
  99. }
  100. PARENT(y) = PARENT(x);
  101. if (PARENT(x) == NIL) {
  102. root = y;
  103. } else if (x==LEFT(PARENT(x))) {
  104. LEFT(PARENT(x)) = y;
  105. } else {
  106. RIGHT(PARENT(x))= y;
  107. }
  108. RIGHT(y) = x;
  109. PARENT(x) = y;
  110. return root;
  111. }
  112. PKNOWNTYPES
  113. RBTreeInsert(
  114. PKNOWNTYPES root,
  115. PKNOWNTYPES z
  116. )
  117. /*++
  118. Routine Description:
  119. Inserts a new node into a tree without preserving the red/black properties.
  120. Should ONLY be called by RBInsert! This is just a simple binary tree
  121. insertion routine.
  122. Arguments:
  123. root - The root of the red/black tree
  124. z - The new node to insert
  125. Return Value:
  126. return-value - The new root of the tree (which could be the same as the
  127. old root).
  128. --*/
  129. {
  130. PKNOWNTYPES x,y;
  131. int i;
  132. y = NIL;
  133. x = root;
  134. LEFT(z) = RIGHT(z) = NIL;
  135. // Find a place to insert z by doing a simple binary search
  136. while (x!=NIL) {
  137. y = x;
  138. i = strcmp(KEY(z), KEY(x));
  139. if (i < 0){
  140. x = LEFT(x);
  141. } else {
  142. x = RIGHT(x);
  143. }
  144. }
  145. // Insert z into the tree
  146. PARENT(z)= y;
  147. if (y==NIL) {
  148. root = z;
  149. } else if (i<0) {
  150. LEFT(y) = z;
  151. } else {
  152. RIGHT(y) = z;
  153. }
  154. return root;
  155. }
  156. VOID
  157. RBInsert(
  158. PRBTREE ptree,
  159. PKNOWNTYPES x
  160. )
  161. /*++
  162. Routine Description:
  163. Inserts a node into a red/black tree while preserving the red/black
  164. properties.
  165. Arguments:
  166. root - The root of the red/black tree
  167. z - The new node to insert
  168. Return Value:
  169. return-value - The new root of the tree (which could be the same as
  170. the old root).
  171. --*/
  172. {
  173. PKNOWNTYPES root = ptree->pRoot;
  174. PKNOWNTYPES y;
  175. // Make a linked-list of nodes for easy deletion
  176. x->Next = ptree->pLastNodeInserted;
  177. ptree->pLastNodeInserted = x;
  178. // Insert x into the tree without preserving the red/black properties
  179. root = RBTreeInsert (root, x);
  180. COLOR(x) = RED;
  181. // We can stop fixing the tree when either:
  182. // 1) We got to the root
  183. // 2) x has a BLACK parent (the tree obeys the red/black properties,
  184. // because no RED parent has a RED child.
  185. while ((x != root) && (COLOR(PARENT(x)) == RED)) {
  186. if (PARENT(x) == LEFT(PARENT(PARENT(x)))) {
  187. // Parent of x is a left child with sibling y.
  188. y = RIGHT(PARENT(PARENT(x)));
  189. if (COLOR(y) == RED) {
  190. // Since y is red, just change everyone's color and try again
  191. // with x's grandfather
  192. COLOR (PARENT (x)) = BLACK;
  193. COLOR(y) = BLACK;
  194. COLOR(PARENT(PARENT(x))) = RED;
  195. x = PARENT(PARENT(x));
  196. } else if (x == RIGHT (PARENT (x))) {
  197. // Here y is BLACK and x is a right child. A left rotation
  198. // at x would prepare us for the next case
  199. x = PARENT(x);
  200. root = RBLeftRotate (root, x);
  201. } else {
  202. // Here y is BLACK and x is a left child. We fix the tree by
  203. // switching the colors of x's parent and grandparent and
  204. // doing a right rotation at x's grandparent.
  205. COLOR (PARENT (x)) = BLACK;
  206. COLOR (PARENT (PARENT (x))) = RED;
  207. root = RBRightRotate (root, PARENT(PARENT(x)));
  208. }
  209. } else {
  210. // Parent of x is a right child with sibling y.
  211. y = LEFT(PARENT(PARENT(x)));
  212. if (COLOR(y) == RED) {
  213. // Since y is red, just change everyone's color and try again
  214. // with x's grandfather
  215. COLOR (PARENT (x)) = BLACK;
  216. COLOR(y) = BLACK;
  217. COLOR(PARENT(PARENT(x))) = RED;
  218. x = PARENT(PARENT(x));
  219. } else if (x == LEFT (PARENT (x))) {
  220. // Here y is BLACK and x is a left child. A right rotation
  221. // at x would prepare us for the next case
  222. x = PARENT(x);
  223. root = RBRightRotate (root, x);
  224. } else {
  225. // Here y is BLACK and x is a right child. We fix the tree by
  226. // switching the colors of x's parent and grandparent and
  227. // doing a left rotation at x's grandparent.
  228. COLOR (PARENT (x)) = BLACK;
  229. COLOR (PARENT (PARENT (x))) = RED;
  230. root = RBLeftRotate (root, PARENT(PARENT(x)));
  231. }
  232. }
  233. } // end of while loop
  234. COLOR(root) = BLACK;
  235. ptree->pRoot= root;
  236. }
  237. PKNOWNTYPES
  238. RBFind(
  239. PRBTREE ptree,
  240. char *Name
  241. )
  242. /*++
  243. Routine Description:
  244. Finds a node in the red black tree given a name
  245. Arguments:
  246. root - The root of the red/black tree
  247. name - The name corresponding to the node to be searched for.
  248. Return Value:
  249. return-value - The node in the tree (entry point of code containing name), or
  250. NULL if not found.
  251. --*/
  252. {
  253. int i;
  254. PKNOWNTYPES root = ptree->pRoot;
  255. while (root != NIL) {
  256. i = strcmp(Name, KEY(root));
  257. if (i < 0) {
  258. root = LEFT(root);
  259. } else if (i > 0) {
  260. root = RIGHT(root);
  261. } else {
  262. return root;
  263. }
  264. }
  265. return NULL; // Range not found
  266. }
  267. PKNOWNTYPES
  268. RBTreeSuccessor(
  269. PKNOWNTYPES x
  270. )
  271. /*++
  272. Routine Description:
  273. Returns the successor of a node in a binary tree (the successor of x
  274. is defined to be the node which just follows x in an inorder
  275. traversal of the tree).
  276. Arguments:
  277. x - The node whose successor is to be returned
  278. Return Value:
  279. return-value - The successor of x
  280. --*/
  281. {
  282. PKNOWNTYPES y;
  283. // If x has a right child, the successor is the leftmost node to the
  284. // right of x.
  285. if (RIGHT(x) != NIL) {
  286. x = RIGHT(x);
  287. while (LEFT(x) != NIL) {
  288. x = LEFT(x);
  289. }
  290. return x;
  291. }
  292. // Else the successor is an ancestor with a left child on the path to x
  293. y = PARENT(x);
  294. while ((y != NIL) && (x == RIGHT(y))) {
  295. x = y;
  296. y = PARENT(y);
  297. }
  298. return y;
  299. }
  300. PKNOWNTYPES
  301. RBDeleteFixup(
  302. PKNOWNTYPES root,
  303. PKNOWNTYPES x
  304. )
  305. /*++
  306. Routine Description:
  307. Fixes the red/black tree after a delete operation. Should only be
  308. called by RBDelete
  309. Arguments:
  310. root - The root of the red/black tree
  311. x - Either a child of x, or or a child or x's successor
  312. Return Value:
  313. return-value - The new root of the red/black tree
  314. --*/
  315. {
  316. PKNOWNTYPES w;
  317. // We stop when we either reached the root, or reached a red node (which
  318. // means that property 4 is no longer violated).
  319. while ((x!=root) && (COLOR(x)==BLACK)) {
  320. if (x == LEFT(PARENT(x))) {
  321. // x is a left child with sibling w
  322. w = RIGHT(PARENT(x));
  323. if (COLOR(w) == RED) {
  324. // If w is red it must have black children. We can switch
  325. // the colors of w and its parent and perform a left
  326. // rotation to bring w to the top. This brings us to one
  327. // of the other cases.
  328. COLOR(w) = BLACK;
  329. COLOR(PARENT(x)) = RED;
  330. root = RBLeftRotate (root, PARENT(x));
  331. w = RIGHT(PARENT(x));
  332. }
  333. if ((COLOR(LEFT(w)) == BLACK) && (COLOR(RIGHT(w)) == BLACK)) {
  334. // Here w is black and has two black children. We can thus
  335. // change w's color to red and continue.
  336. COLOR(w) = RED;
  337. x = PARENT(x);
  338. } else {
  339. if (COLOR(RIGHT(w)) == BLACK) {
  340. // Here w is black, its left child is red, and its right child
  341. // is black. We switch the colors of w and its left child,
  342. // and perform a left rotation at w which brings us to the next
  343. // case.
  344. COLOR(LEFT(w)) = BLACK;
  345. COLOR(w) = RED;
  346. root = RBRightRotate (root, w);
  347. w = RIGHT(PARENT(x));
  348. }
  349. // Here w is black and has a red right child. We change w's
  350. // color to that of its parent, and make its parent and right
  351. // child black. Then a left rotation brings w to the top.
  352. // Making x the root ensures that the while loop terminates.
  353. COLOR(w) = COLOR(PARENT(x));
  354. COLOR(PARENT(x)) = BLACK;
  355. COLOR(RIGHT(w)) = BLACK;
  356. root = RBLeftRotate (root, PARENT(x));
  357. x = root;
  358. }
  359. } else {
  360. // The symmetric case: x is a right child with sibling w.
  361. w = LEFT(PARENT(x));
  362. if (COLOR(w) == RED) {
  363. COLOR(w) = BLACK;
  364. COLOR(PARENT(x)) = RED;
  365. root = RBRightRotate (root, PARENT(x));
  366. w = LEFT(PARENT(x));
  367. }
  368. if ((COLOR(LEFT(w)) == BLACK) && (COLOR(RIGHT(w)) == BLACK)) {
  369. COLOR(w) = RED;
  370. x = PARENT(x);
  371. } else {
  372. if (COLOR(LEFT(w)) == BLACK) {
  373. COLOR(RIGHT(w)) = BLACK;
  374. COLOR(w) = RED;
  375. root = RBLeftRotate (root, w);
  376. w = LEFT(PARENT(x));
  377. }
  378. COLOR(w) = COLOR(PARENT(x));
  379. COLOR(PARENT(x)) = BLACK;
  380. COLOR(LEFT(w)) = BLACK;
  381. root = RBRightRotate (root, PARENT(x));
  382. x = root;
  383. }
  384. }
  385. } // end of while loop
  386. //printf ("Changing color at %i to BLACK\n", x->intelColor);
  387. COLOR(x) = BLACK;
  388. return root;
  389. }
  390. PKNOWNTYPES
  391. RBDelete(
  392. PRBTREE ptree,
  393. PKNOWNTYPES z
  394. )
  395. /*++
  396. Routine Description:
  397. Deletes a node in a red/black tree while preserving the red/black
  398. properties.
  399. Arguments:
  400. root - The root of the red/black tree
  401. z - The node to be deleted
  402. Return Value:
  403. return-value - The new root of the red/black tree
  404. --*/
  405. {
  406. PKNOWNTYPES x,y;
  407. PKNOWNTYPES root = ptree->pRoot;
  408. COL c;
  409. // It's easy to delete a node with at most one child: we only need to
  410. // remove it and put the child in its place. It z has at most one child,
  411. // we can just remove it. Otherwise we'll replace it with its successor
  412. // (which is guaranteed to have at most one child, or else one of its
  413. // children would be the succecssor), and delete the successor.
  414. if ((LEFT(z) == NIL) || (RIGHT(z) == NIL)) {
  415. y = z;
  416. } else {
  417. y = RBTreeSuccessor(z);
  418. }
  419. // Recall that y has at most one child. If y has one child, x is set to
  420. // it. Else x will be set to NIL which is OK. This way we don't have
  421. // to worry about this special case.
  422. if (LEFT(y) != NIL){
  423. x = LEFT(y);
  424. } else {
  425. x = RIGHT(y);
  426. }
  427. // Now we will remove y from the tree
  428. PARENT(x) = PARENT(y);
  429. if (PARENT(y) == NIL) {
  430. root = x;
  431. } else if (y == LEFT(PARENT(y))) {
  432. LEFT(PARENT(y)) = x;
  433. } else {
  434. RIGHT(PARENT(y)) = x;
  435. }
  436. if (PARENT(x) == z) {
  437. PARENT(x) = y;
  438. }
  439. c = COLOR(y);
  440. // Since each node has lots of fields (fields may also change during
  441. // the lifetime of this code), I found it safer to copy the
  442. // pointers as opposed to data.
  443. if (y!=z) { // Now swapping y and z, but remembering color of y
  444. PARENT(y) = PARENT(z);
  445. if (root == z) {
  446. root = y;
  447. } else if (z == RIGHT(PARENT(z))) {
  448. RIGHT(PARENT(z)) = y;
  449. } else {
  450. LEFT(PARENT(z)) = y;
  451. }
  452. LEFT(y) = LEFT(z);
  453. if (LEFT(y) != NIL) {
  454. PARENT(LEFT(y)) = y;
  455. }
  456. RIGHT(y) = RIGHT(z);
  457. if (RIGHT(y) != NIL) {
  458. PARENT(RIGHT(y)) = y;
  459. }
  460. COLOR(y) = COLOR(z);
  461. }
  462. // Need to fix the tree (fourth red/black property).
  463. if (c == BLACK) {
  464. root = RBDeleteFixup (root, x);
  465. }
  466. return root;
  467. }