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.

602 lines
15 KiB

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