《操作系统》的实验代码。
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.

528 lines
15 KiB

10 years ago
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <kmalloc.h>
  5. #include <rb_tree.h>
  6. #include <assert.h>
  7. /* rb_node_create - create a new rb_node */
  8. static inline rb_node *
  9. rb_node_create(void) {
  10. return kmalloc(sizeof(rb_node));
  11. }
  12. /* rb_tree_empty - tests if tree is empty */
  13. static inline bool
  14. rb_tree_empty(rb_tree *tree) {
  15. rb_node *nil = tree->nil, *root = tree->root;
  16. return root->left == nil;
  17. }
  18. /* *
  19. * rb_tree_create - creates a new red-black tree, the 'compare' function
  20. * is required and returns 'NULL' if failed.
  21. *
  22. * Note that, root->left should always point to the node that is the root
  23. * of the tree. And nil points to a 'NULL' node which should always be
  24. * black and may have arbitrary children and parent node.
  25. * */
  26. rb_tree *
  27. rb_tree_create(int (*compare)(rb_node *node1, rb_node *node2)) {
  28. assert(compare != NULL);
  29. rb_tree *tree;
  30. rb_node *nil, *root;
  31. if ((tree = kmalloc(sizeof(rb_tree))) == NULL) {
  32. goto bad_tree;
  33. }
  34. tree->compare = compare;
  35. if ((nil = rb_node_create()) == NULL) {
  36. goto bad_node_cleanup_tree;
  37. }
  38. nil->parent = nil->left = nil->right = nil;
  39. nil->red = 0;
  40. tree->nil = nil;
  41. if ((root = rb_node_create()) == NULL) {
  42. goto bad_node_cleanup_nil;
  43. }
  44. root->parent = root->left = root->right = nil;
  45. root->red = 0;
  46. tree->root = root;
  47. return tree;
  48. bad_node_cleanup_nil:
  49. kfree(nil);
  50. bad_node_cleanup_tree:
  51. kfree(tree);
  52. bad_tree:
  53. return NULL;
  54. }
  55. /* *
  56. * FUNC_ROTATE - rotates as described in "Introduction to Algorithm".
  57. *
  58. * For example, FUNC_ROTATE(rb_left_rotate, left, right) can be expaned to a
  59. * left-rotate function, which requires an red-black 'tree' and a node 'x'
  60. * to be rotated on. Basically, this function, named rb_left_rotate, makes the
  61. * parent of 'x' be the left child of 'x', 'x' the parent of its parent before
  62. * rotation and finally fixes other nodes accordingly.
  63. *
  64. * FUNC_ROTATE(xx, left, right) means left-rotate,
  65. * and FUNC_ROTATE(xx, right, left) means right-rotate.
  66. * */
  67. #define FUNC_ROTATE(func_name, _left, _right) \
  68. static void \
  69. func_name(rb_tree *tree, rb_node *x) { \
  70. rb_node *nil = tree->nil, *y = x->_right; \
  71. assert(x != tree->root && x != nil && y != nil); \
  72. x->_right = y->_left; \
  73. if (y->_left != nil) { \
  74. y->_left->parent = x; \
  75. } \
  76. y->parent = x->parent; \
  77. if (x == x->parent->_left) { \
  78. x->parent->_left = y; \
  79. } \
  80. else { \
  81. x->parent->_right = y; \
  82. } \
  83. y->_left = x; \
  84. x->parent = y; \
  85. assert(!(nil->red)); \
  86. }
  87. FUNC_ROTATE(rb_left_rotate, left, right);
  88. FUNC_ROTATE(rb_right_rotate, right, left);
  89. #undef FUNC_ROTATE
  90. #define COMPARE(tree, node1, node2) \
  91. ((tree))->compare((node1), (node2))
  92. /* *
  93. * rb_insert_binary - insert @node to red-black @tree as if it were
  94. * a regular binary tree. This function is only intended to be called
  95. * by function rb_insert.
  96. * */
  97. static inline void
  98. rb_insert_binary(rb_tree *tree, rb_node *node) {
  99. rb_node *x, *y, *z = node, *nil = tree->nil, *root = tree->root;
  100. z->left = z->right = nil;
  101. y = root, x = y->left;
  102. while (x != nil) {
  103. y = x;
  104. x = (COMPARE(tree, x, node) > 0) ? x->left : x->right;
  105. }
  106. z->parent = y;
  107. if (y == root || COMPARE(tree, y, z) > 0) {
  108. y->left = z;
  109. }
  110. else {
  111. y->right = z;
  112. }
  113. }
  114. /* rb_insert - insert a node to red-black tree */
  115. void
  116. rb_insert(rb_tree *tree, rb_node *node) {
  117. rb_insert_binary(tree, node);
  118. node->red = 1;
  119. rb_node *x = node, *y;
  120. #define RB_INSERT_SUB(_left, _right) \
  121. do { \
  122. y = x->parent->parent->_right; \
  123. if (y->red) { \
  124. x->parent->red = 0; \
  125. y->red = 0; \
  126. x->parent->parent->red = 1; \
  127. x = x->parent->parent; \
  128. } \
  129. else { \
  130. if (x == x->parent->_right) { \
  131. x = x->parent; \
  132. rb_##_left##_rotate(tree, x); \
  133. } \
  134. x->parent->red = 0; \
  135. x->parent->parent->red = 1; \
  136. rb_##_right##_rotate(tree, x->parent->parent); \
  137. } \
  138. } while (0)
  139. while (x->parent->red) {
  140. if (x->parent == x->parent->parent->left) {
  141. RB_INSERT_SUB(left, right);
  142. }
  143. else {
  144. RB_INSERT_SUB(right, left);
  145. }
  146. }
  147. tree->root->left->red = 0;
  148. assert(!(tree->nil->red) && !(tree->root->red));
  149. #undef RB_INSERT_SUB
  150. }
  151. /* *
  152. * rb_tree_successor - returns the successor of @node, or nil
  153. * if no successor exists. Make sure that @node must belong to @tree,
  154. * and this function should only be called by rb_node_prev.
  155. * */
  156. static inline rb_node *
  157. rb_tree_successor(rb_tree *tree, rb_node *node) {
  158. rb_node *x = node, *y, *nil = tree->nil;
  159. if ((y = x->right) != nil) {
  160. while (y->left != nil) {
  161. y = y->left;
  162. }
  163. return y;
  164. }
  165. else {
  166. y = x->parent;
  167. while (x == y->right) {
  168. x = y, y = y->parent;
  169. }
  170. if (y == tree->root) {
  171. return nil;
  172. }
  173. return y;
  174. }
  175. }
  176. /* *
  177. * rb_tree_predecessor - returns the predecessor of @node, or nil
  178. * if no predecessor exists, likes rb_tree_successor.
  179. * */
  180. static inline rb_node *
  181. rb_tree_predecessor(rb_tree *tree, rb_node *node) {
  182. rb_node *x = node, *y, *nil = tree->nil;
  183. if ((y = x->left) != nil) {
  184. while (y->right != nil) {
  185. y = y->right;
  186. }
  187. return y;
  188. }
  189. else {
  190. y = x->parent;
  191. while (x == y->left) {
  192. if (y == tree->root) {
  193. return nil;
  194. }
  195. x = y, y = y->parent;
  196. }
  197. return y;
  198. }
  199. }
  200. /* *
  201. * rb_search - returns a node with value 'equal' to @key (according to
  202. * function @compare). If there're multiple nodes with value 'equal' to @key,
  203. * the functions returns the one highest in the tree.
  204. * */
  205. rb_node *
  206. rb_search(rb_tree *tree, int (*compare)(rb_node *node, void *key), void *key) {
  207. rb_node *nil = tree->nil, *node = tree->root->left;
  208. int r;
  209. while (node != nil && (r = compare(node, key)) != 0) {
  210. node = (r > 0) ? node->left : node->right;
  211. }
  212. return (node != nil) ? node : NULL;
  213. }
  214. /* *
  215. * rb_delete_fixup - performs rotations and changes colors to restore
  216. * red-black properties after a node is deleted.
  217. * */
  218. static void
  219. rb_delete_fixup(rb_tree *tree, rb_node *node) {
  220. rb_node *x = node, *w, *root = tree->root->left;
  221. #define RB_DELETE_FIXUP_SUB(_left, _right) \
  222. do { \
  223. w = x->parent->_right; \
  224. if (w->red) { \
  225. w->red = 0; \
  226. x->parent->red = 1; \
  227. rb_##_left##_rotate(tree, x->parent); \
  228. w = x->parent->_right; \
  229. } \
  230. if (!w->_left->red && !w->_right->red) { \
  231. w->red = 1; \
  232. x = x->parent; \
  233. } \
  234. else { \
  235. if (!w->_right->red) { \
  236. w->_left->red = 0; \
  237. w->red = 1; \
  238. rb_##_right##_rotate(tree, w); \
  239. w = x->parent->_right; \
  240. } \
  241. w->red = x->parent->red; \
  242. x->parent->red = 0; \
  243. w->_right->red = 0; \
  244. rb_##_left##_rotate(tree, x->parent); \
  245. x = root; \
  246. } \
  247. } while (0)
  248. while (x != root && !x->red) {
  249. if (x == x->parent->left) {
  250. RB_DELETE_FIXUP_SUB(left, right);
  251. }
  252. else {
  253. RB_DELETE_FIXUP_SUB(right, left);
  254. }
  255. }
  256. x->red = 0;
  257. #undef RB_DELETE_FIXUP_SUB
  258. }
  259. /* *
  260. * rb_delete - deletes @node from @tree, and calls rb_delete_fixup to
  261. * restore red-black properties.
  262. * */
  263. void
  264. rb_delete(rb_tree *tree, rb_node *node) {
  265. rb_node *x, *y, *z = node;
  266. rb_node *nil = tree->nil, *root = tree->root;
  267. y = (z->left == nil || z->right == nil) ? z : rb_tree_successor(tree, z);
  268. x = (y->left != nil) ? y->left : y->right;
  269. assert(y != root && y != nil);
  270. x->parent = y->parent;
  271. if (y == y->parent->left) {
  272. y->parent->left = x;
  273. }
  274. else {
  275. y->parent->right = x;
  276. }
  277. bool need_fixup = !(y->red);
  278. if (y != z) {
  279. if (z == z->parent->left) {
  280. z->parent->left = y;
  281. }
  282. else {
  283. z->parent->right = y;
  284. }
  285. z->left->parent = z->right->parent = y;
  286. *y = *z;
  287. }
  288. if (need_fixup) {
  289. rb_delete_fixup(tree, x);
  290. }
  291. }
  292. /* rb_tree_destroy - destroy a tree and free memory */
  293. void
  294. rb_tree_destroy(rb_tree *tree) {
  295. kfree(tree->root);
  296. kfree(tree->nil);
  297. kfree(tree);
  298. }
  299. /* *
  300. * rb_node_prev - returns the predecessor node of @node in @tree,
  301. * or 'NULL' if no predecessor exists.
  302. * */
  303. rb_node *
  304. rb_node_prev(rb_tree *tree, rb_node *node) {
  305. rb_node *prev = rb_tree_predecessor(tree, node);
  306. return (prev != tree->nil) ? prev : NULL;
  307. }
  308. /* *
  309. * rb_node_next - returns the successor node of @node in @tree,
  310. * or 'NULL' if no successor exists.
  311. * */
  312. rb_node *
  313. rb_node_next(rb_tree *tree, rb_node *node) {
  314. rb_node *next = rb_tree_successor(tree, node);
  315. return (next != tree->nil) ? next : NULL;
  316. }
  317. /* rb_node_root - returns the root node of a @tree, or 'NULL' if tree is empty */
  318. rb_node *
  319. rb_node_root(rb_tree *tree) {
  320. rb_node *node = tree->root->left;
  321. return (node != tree->nil) ? node : NULL;
  322. }
  323. /* rb_node_left - gets the left child of @node, or 'NULL' if no such node */
  324. rb_node *
  325. rb_node_left(rb_tree *tree, rb_node *node) {
  326. rb_node *left = node->left;
  327. return (left != tree->nil) ? left : NULL;
  328. }
  329. /* rb_node_right - gets the right child of @node, or 'NULL' if no such node */
  330. rb_node *
  331. rb_node_right(rb_tree *tree, rb_node *node) {
  332. rb_node *right = node->right;
  333. return (right != tree->nil) ? right : NULL;
  334. }
  335. int
  336. check_tree(rb_tree *tree, rb_node *node) {
  337. rb_node *nil = tree->nil;
  338. if (node == nil) {
  339. assert(!node->red);
  340. return 1;
  341. }
  342. if (node->left != nil) {
  343. assert(COMPARE(tree, node, node->left) >= 0);
  344. assert(node->left->parent == node);
  345. }
  346. if (node->right != nil) {
  347. assert(COMPARE(tree, node, node->right) <= 0);
  348. assert(node->right->parent == node);
  349. }
  350. if (node->red) {
  351. assert(!node->left->red && !node->right->red);
  352. }
  353. int hb_left = check_tree(tree, node->left);
  354. int hb_right = check_tree(tree, node->right);
  355. assert(hb_left == hb_right);
  356. int hb = hb_left;
  357. if (!node->red) {
  358. hb ++;
  359. }
  360. return hb;
  361. }
  362. static void *
  363. check_safe_kmalloc(size_t size) {
  364. void *ret = kmalloc(size);
  365. assert(ret != NULL);
  366. return ret;
  367. }
  368. struct check_data {
  369. long data;
  370. rb_node rb_link;
  371. };
  372. #define rbn2data(node) \
  373. (to_struct(node, struct check_data, rb_link))
  374. static inline int
  375. check_compare1(rb_node *node1, rb_node *node2) {
  376. return rbn2data(node1)->data - rbn2data(node2)->data;
  377. }
  378. static inline int
  379. check_compare2(rb_node *node, void *key) {
  380. return rbn2data(node)->data - (long)key;
  381. }
  382. void
  383. check_rb_tree(void) {
  384. rb_tree *tree = rb_tree_create(check_compare1);
  385. assert(tree != NULL);
  386. rb_node *nil = tree->nil, *root = tree->root;
  387. assert(!nil->red && root->left == nil);
  388. int total = 1000;
  389. struct check_data **all = check_safe_kmalloc(sizeof(struct check_data *) * total);
  390. long i;
  391. for (i = 0; i < total; i ++) {
  392. all[i] = check_safe_kmalloc(sizeof(struct check_data));
  393. all[i]->data = i;
  394. }
  395. int *mark = check_safe_kmalloc(sizeof(int) * total);
  396. memset(mark, 0, sizeof(int) * total);
  397. for (i = 0; i < total; i ++) {
  398. mark[all[i]->data] = 1;
  399. }
  400. for (i = 0; i < total; i ++) {
  401. assert(mark[i] == 1);
  402. }
  403. for (i = 0; i < total; i ++) {
  404. int j = (rand() % (total - i)) + i;
  405. struct check_data *z = all[i];
  406. all[i] = all[j];
  407. all[j] = z;
  408. }
  409. memset(mark, 0, sizeof(int) * total);
  410. for (i = 0; i < total; i ++) {
  411. mark[all[i]->data] = 1;
  412. }
  413. for (i = 0; i < total; i ++) {
  414. assert(mark[i] == 1);
  415. }
  416. for (i = 0; i < total; i ++) {
  417. rb_insert(tree, &(all[i]->rb_link));
  418. check_tree(tree, root->left);
  419. }
  420. rb_node *node;
  421. for (i = 0; i < total; i ++) {
  422. node = rb_search(tree, check_compare2, (void *)(all[i]->data));
  423. assert(node != NULL && node == &(all[i]->rb_link));
  424. }
  425. for (i = 0; i < total; i ++) {
  426. node = rb_search(tree, check_compare2, (void *)i);
  427. assert(node != NULL && rbn2data(node)->data == i);
  428. rb_delete(tree, node);
  429. check_tree(tree, root->left);
  430. }
  431. assert(!nil->red && root->left == nil);
  432. long max = 32;
  433. if (max > total) {
  434. max = total;
  435. }
  436. for (i = 0; i < max; i ++) {
  437. all[i]->data = max;
  438. rb_insert(tree, &(all[i]->rb_link));
  439. check_tree(tree, root->left);
  440. }
  441. for (i = 0; i < max; i ++) {
  442. node = rb_search(tree, check_compare2, (void *)max);
  443. assert(node != NULL && rbn2data(node)->data == max);
  444. rb_delete(tree, node);
  445. check_tree(tree, root->left);
  446. }
  447. assert(rb_tree_empty(tree));
  448. for (i = 0; i < total; i ++) {
  449. rb_insert(tree, &(all[i]->rb_link));
  450. check_tree(tree, root->left);
  451. }
  452. rb_tree_destroy(tree);
  453. for (i = 0; i < total; i ++) {
  454. kfree(all[i]);
  455. }
  456. kfree(mark);
  457. kfree(all);
  458. }