tree.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:13k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    
  3.    This library is free software; you can redistribute it and/or
  4.    modify it under the terms of the GNU Library General Public
  5.    License as published by the Free Software Foundation; either
  6.    version 2 of the License, or (at your option) any later version.
  7.    
  8.    This library is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11.    Library General Public License for more details.
  12.    
  13.    You should have received a copy of the GNU Library General Public
  14.    License along with this library; if not, write to the Free
  15.    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  16.    MA 02111-1307, USA */
  17. /*
  18.   Code for handling red-black (balanced) binary trees.
  19.   key in tree is allocated accrding to following:
  20.   1) If free_element function is given to init_tree or size < 0 then tree
  21.      will not allocate keys and only a pointer to each key is saved in tree.
  22.      key_sizes must be 0 to init and search.
  23.      compare and search functions uses and returns key-pointer.
  24.   2) if key_size is given to init_tree then each node will continue the
  25.      key and calls to insert_key may increase length of key.
  26.      if key_size > sizeof(pointer) and key_size is a multiple of 8 (double
  27.      allign) then key will be put on a 8 alligned adress. Else
  28.      the key will be on adress (element+1). This is transparent for user
  29.      compare and search functions uses a pointer to given key-argument.
  30.   3) If init_tree - keysize is 0 then key_size must be given to tree_insert
  31.      and tree_insert will alloc space for key.
  32.      compare and search functions uses a pointer to given key-argument.
  33.   The actual key in TREE_ELEMENT is saved as a pointer or after the
  34.   TREE_ELEMENT struct.
  35.   If one uses only pointers in tree one can use tree_set_pointer() to
  36.   change address of data.
  37.   Copyright Monty Program KB.
  38.   By monty.
  39. */
  40. #include "mysys_priv.h"
  41. #include <m_string.h>
  42. #include <my_tree.h>
  43. #define BLACK 1
  44. #define RED 0
  45. #define DEFAULT_ALLOC_SIZE (8192-MALLOC_OVERHEAD)
  46. static void delete_tree_element(TREE *,TREE_ELEMENT *);
  47. static int tree_walk_left_root_right(TREE *,TREE_ELEMENT *,
  48.      tree_walk_action,void *);
  49. static int tree_walk_right_root_left(TREE *,TREE_ELEMENT *,
  50.      tree_walk_action,void *);
  51. static void left_rotate(TREE_ELEMENT **parent,TREE_ELEMENT *leaf);
  52. static void right_rotate(TREE_ELEMENT **parent, TREE_ELEMENT *leaf);
  53. static void rb_insert(TREE *tree,TREE_ELEMENT ***parent,
  54.       TREE_ELEMENT *leaf);
  55. static void rb_delete_fixup(TREE *tree,TREE_ELEMENT ***parent);
  56. /* The actuall code for handling binary trees */
  57. void init_tree(TREE *tree, uint default_alloc_size, int size,
  58.        qsort_cmp compare, my_bool with_delete,
  59.        void (*free_element) (void *))
  60. {
  61.   DBUG_ENTER("init_tree");
  62.   DBUG_PRINT("enter",("tree: %lx  size: %d",tree,size));
  63.   if (!default_alloc_size)
  64.     default_alloc_size= DEFAULT_ALLOC_SIZE;
  65.   bzero((gptr) &tree->null_element,sizeof(tree->null_element));
  66.   tree->root= &tree->null_element;
  67.   tree->compare=compare;
  68.   tree->size_of_element=size > 0 ? (uint) size : 0;
  69.   tree->free=free_element;
  70.   tree->elements_in_tree=0;
  71.   tree->null_element.colour=BLACK;
  72.   tree->null_element.left=tree->null_element.right=0;
  73.   if (!free_element && size >= 0 &&
  74.       ((uint) size <= sizeof(void*) || ((uint) size & (sizeof(void*)-1))))
  75.   {
  76.     tree->offset_to_key=sizeof(TREE_ELEMENT); /* Put key after element */
  77.     /* Fix allocation size so that we don't loose any memory */
  78.     default_alloc_size/=(sizeof(TREE_ELEMENT)+size);
  79.     if (!default_alloc_size)
  80.       default_alloc_size=1;
  81.     default_alloc_size*=(sizeof(TREE_ELEMENT)+size);
  82.   }
  83.   else
  84.   {
  85.     tree->offset_to_key=0; /* use key through pointer */
  86.     tree->size_of_element+=sizeof(void*);
  87.   }
  88.   if (!(tree->with_delete=with_delete))
  89.   {
  90.     init_alloc_root(&tree->mem_root, default_alloc_size,0);
  91.     tree->mem_root.min_malloc=(sizeof(TREE_ELEMENT)+tree->size_of_element);
  92.   }
  93.   DBUG_VOID_RETURN;
  94. }
  95. void delete_tree(TREE *tree)
  96. {
  97.   DBUG_ENTER("delete_tree");
  98.   DBUG_PRINT("enter",("tree: %lx",tree));
  99.   if (tree->root) /* If initialized */
  100.   {
  101.     if (tree->with_delete)
  102.       delete_tree_element(tree,tree->root);
  103.     else
  104.     {
  105.       if (tree->free)
  106. delete_tree_element(tree,tree->root);
  107.       free_root(&tree->mem_root,MYF(0));
  108.     }
  109.   }
  110.   tree->root= &tree->null_element;
  111.   tree->elements_in_tree=0;
  112.   DBUG_VOID_RETURN;
  113. }
  114. static void delete_tree_element(TREE *tree, TREE_ELEMENT *element)
  115. {
  116.   if (element != &tree->null_element)
  117.   {
  118.     delete_tree_element(tree,element->left);
  119.     delete_tree_element(tree,element->right);
  120.     if (tree->free)
  121.       (*tree->free)(ELEMENT_KEY(tree,element));
  122.     if (tree->with_delete)
  123.       my_free((void*) element,MYF(0));
  124.   }
  125. }
  126. /* Code for insert, search and delete of elements */
  127. /*   parent[0] = & parent[-1][0]->left ||
  128.      parent[0] = & parent[-1][0]->right */
  129. TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size)
  130. {
  131.   int cmp;
  132.   TREE_ELEMENT *element,***parent;
  133.   parent= tree->parents;
  134.   *parent = &tree->root; element= tree->root;
  135.   for (;;)
  136.   {
  137.     if (element == &tree->null_element ||
  138. (cmp=(*tree->compare)(ELEMENT_KEY(tree,element),key)) == 0)
  139.       break;
  140.     if (cmp < 0)
  141.     {
  142.       *++parent= &element->right; element= element->right;
  143.     }
  144.     else
  145.     {
  146.       *++parent = &element->left; element= element->left;
  147.     }
  148.   }
  149.   if (element == &tree->null_element)
  150.   {
  151.     key_size+=tree->size_of_element;
  152.     if (tree->with_delete)
  153.       element=(TREE_ELEMENT *) my_malloc(sizeof(TREE_ELEMENT)+key_size,
  154.  MYF(MY_WME));
  155.     else
  156.       element=(TREE_ELEMENT *)
  157. alloc_root(&tree->mem_root,sizeof(TREE_ELEMENT)+key_size);
  158.     if (!element)
  159.       return(NULL);
  160.     **parent=element;
  161.     element->left=element->right= &tree->null_element;
  162.     if (!tree->offset_to_key)
  163.     {
  164.       if (key_size == sizeof(void*))  /* no length, save pointer */
  165. *((void**) (element+1))=key;
  166.       else
  167.       {
  168. *((void**) (element+1))= (void*) ((void **) (element+1)+1);
  169. memcpy((byte*) *((void **) (element+1)),key,
  170.        (size_t) (key_size-sizeof(void*)));
  171.       }
  172.     }
  173.     else
  174.       memcpy((byte*) element+tree->offset_to_key,key,(size_t) key_size);
  175.     element->count=1; /* May give warning in purify */
  176.     tree->elements_in_tree++;
  177.     rb_insert(tree,parent,element); /* rebalance tree */
  178.   }
  179.   else
  180.     element->count++;
  181.   return element;
  182. }
  183. int tree_delete(TREE *tree, void *key)
  184. {
  185.   int cmp,remove_colour;
  186.   TREE_ELEMENT *element,***parent, ***org_parent, *nod;
  187.   if (!tree->with_delete)
  188.     return 1; /* not allowed */
  189.   parent= tree->parents;
  190.   *parent= &tree->root; element= tree->root;
  191.   for (;;)
  192.   {
  193.     if (element == &tree->null_element)
  194.       return 1; /* Was not in tree */
  195.     if ((cmp=(*tree->compare)(ELEMENT_KEY(tree,element),key)) == 0)
  196.       break;
  197.     if (cmp < 0)
  198.     {
  199.       *++parent= &element->right; element= element->right;
  200.     }
  201.     else
  202.     {
  203.       *++parent = &element->left; element= element->left;
  204.     }
  205.   }
  206.   if (element->left == &tree->null_element)
  207.   {
  208.     (**parent)=element->right;
  209.     remove_colour= element->colour;
  210.   }
  211.   else if (element->right == &tree->null_element)
  212.   {
  213.     (**parent)=element->left;
  214.     remove_colour= element->colour;
  215.   }
  216.   else
  217.   {
  218.     org_parent= parent;
  219.     *++parent= &element->right; nod= element->right;
  220.     while (nod->left != &tree->null_element)
  221.     {
  222.       *++parent= &nod->left; nod= nod->left;
  223.     }
  224.     (**parent)=nod->right; /* unlink nod from tree */
  225.     remove_colour= nod->colour;
  226.     org_parent[0][0]=nod; /* put y in place of element */
  227.     org_parent[1]= &nod->right;
  228.     nod->left=element->left;
  229.     nod->right=element->right;
  230.     nod->colour=element->colour;
  231.   }
  232.   if (remove_colour == BLACK)
  233.     rb_delete_fixup(tree,parent);
  234.   my_free((gptr) element,MYF(0));
  235.   tree->elements_in_tree--;
  236.   return 0;
  237. }
  238. void *tree_search(TREE *tree, void *key)
  239. {
  240.   int cmp;
  241.   TREE_ELEMENT *element=tree->root;
  242.   for (;;)
  243.   {
  244.     if (element == &tree->null_element)
  245.       return (void*) 0;
  246.     if ((cmp=(*tree->compare)(ELEMENT_KEY(tree,element),key)) == 0)
  247.       return ELEMENT_KEY(tree,element);
  248.     if (cmp < 0)
  249.       element=element->right;
  250.     else
  251.       element=element->left;
  252.   }
  253. }
  254. int tree_walk(TREE *tree, tree_walk_action action, void *argument, TREE_WALK visit)
  255. {
  256.   switch (visit) {
  257.   case left_root_right:
  258.     return tree_walk_left_root_right(tree,tree->root,action,argument);
  259.   case right_root_left:
  260.     return tree_walk_right_root_left(tree,tree->root,action,argument);
  261.   }
  262.   return 0; /* Keep gcc happy */
  263. }
  264. static int tree_walk_left_root_right(TREE *tree, TREE_ELEMENT *element, tree_walk_action action, void *argument)
  265. {
  266.   int error;
  267.   if (element->left) /* Not null_element */
  268.   {
  269.     if ((error=tree_walk_left_root_right(tree,element->left,action,
  270.   argument)) == 0 &&
  271. (error=(*action)(ELEMENT_KEY(tree,element),
  272.   (element_count) element->count,
  273.   argument)) == 0)
  274.       error=tree_walk_left_root_right(tree,element->right,action,argument);
  275.     return error;
  276.   }
  277.   return 0;
  278. }
  279. static int tree_walk_right_root_left(TREE *tree, TREE_ELEMENT *element, tree_walk_action action, void *argument)
  280. {
  281.   int error;
  282.   if (element->right) /* Not null_element */
  283.   {
  284.     if ((error=tree_walk_right_root_left(tree,element->right,action,
  285.   argument)) == 0 &&
  286. (error=(*action)(ELEMENT_KEY(tree,element),
  287.   (element_count) element->count,
  288.   argument)) == 0)
  289.      error=tree_walk_right_root_left(tree,element->left,action,argument);
  290.     return error;
  291.   }
  292.   return 0;
  293. }
  294. /* Functions to fix up the tree after insert and delete */
  295. static void left_rotate(TREE_ELEMENT **parent, TREE_ELEMENT *leaf)
  296. {
  297.   TREE_ELEMENT *y;
  298.   y=leaf->right;
  299.   leaf->right=y->left;
  300.   parent[0]=y;
  301.   y->left=leaf;
  302. }
  303. static void right_rotate(TREE_ELEMENT **parent, TREE_ELEMENT *leaf)
  304. {
  305.   TREE_ELEMENT *x;
  306.   x=leaf->left;
  307.   leaf->left=x->right;
  308.   parent[0]=x;
  309.   x->right=leaf;
  310. }
  311. static void rb_insert(TREE *tree, TREE_ELEMENT ***parent, TREE_ELEMENT *leaf)
  312. {
  313.   TREE_ELEMENT *y,*par,*par2;
  314.   leaf->colour=RED;
  315.   while (leaf != tree->root && (par=parent[-1][0])->colour == RED)
  316.   {
  317.     if (par == (par2=parent[-2][0])->left)
  318.     {
  319.       y= par2->right;
  320.       if (y->colour == RED)
  321.       {
  322. par->colour=BLACK;
  323. y->colour=BLACK;
  324. leaf=par2;
  325. parent-=2;
  326. leaf->colour=RED; /* And the loop continues */
  327.       }
  328.       else
  329.       {
  330. if (leaf == par->right)
  331. {
  332.   left_rotate(parent[-1],par);
  333.   par=leaf; /* leaf is now parent to old leaf */
  334. }
  335. par->colour=BLACK;
  336. par2->colour=RED;
  337. right_rotate(parent[-2],par2);
  338. break;
  339.       }
  340.     }
  341.     else
  342.     {
  343.       y= par2->left;
  344.       if (y->colour == RED)
  345.       {
  346. par->colour=BLACK;
  347. y->colour=BLACK;
  348. leaf=par2;
  349. parent-=2;
  350. leaf->colour=RED; /* And the loop continues */
  351.       }
  352.       else
  353.       {
  354. if (leaf == par->left)
  355. {
  356.   right_rotate(parent[-1],par);
  357.   par=leaf;
  358. }
  359. par->colour=BLACK;
  360. par2->colour=RED;
  361. left_rotate(parent[-2],par2);
  362. break;
  363.       }
  364.     }
  365.   }
  366.   tree->root->colour=BLACK;
  367. }
  368. static void rb_delete_fixup(TREE *tree, TREE_ELEMENT ***parent)
  369. {
  370.   TREE_ELEMENT *x,*w,*par;
  371.   x= **parent;
  372.   while (x != tree->root && x->colour == BLACK)
  373.   {
  374.     if (x == (par=parent[-1][0])->left)
  375.     {
  376.       w=par->right;
  377.       if (w->colour == RED)
  378.       {
  379. w->colour=BLACK;
  380. par->colour=RED;
  381. left_rotate(parent[-1],par);
  382. parent[0]= &w->left;
  383. *++parent= &par->left;
  384. w=par->right;
  385.       }
  386.       if (w->left->colour == BLACK && w->right->colour == BLACK)
  387.       {
  388. w->colour=RED;
  389. x=par;
  390. parent--;
  391.       }
  392.       else
  393.       {
  394. if (w->right->colour == BLACK)
  395. {
  396.   w->left->colour=BLACK;
  397.   w->colour=RED;
  398.   right_rotate(&par->right,w);
  399.   w=par->right;
  400. }
  401. w->colour=par->colour;
  402. par->colour=BLACK;
  403. w->right->colour=BLACK;
  404. left_rotate(parent[-1],par);
  405. x=tree->root;
  406. break;
  407.       }
  408.     }
  409.     else
  410.     {
  411.       w=par->left;
  412.       if (w->colour == RED)
  413.       {
  414. w->colour=BLACK;
  415. par->colour=RED;
  416. right_rotate(parent[-1],par);
  417. parent[0]= &w->right;
  418. *++parent= &par->right;
  419. w=par->left;
  420.       }
  421.       if (w->right->colour == BLACK && w->left->colour == BLACK)
  422.       {
  423. w->colour=RED;
  424. x=par;
  425. parent--;
  426.       }
  427.       else
  428.       {
  429. if (w->left->colour == BLACK)
  430. {
  431.   w->right->colour=BLACK;
  432.   w->colour=RED;
  433.   left_rotate(&par->left,w);
  434.   w=par->left;
  435. }
  436. w->colour=par->colour;
  437. par->colour=BLACK;
  438. w->left->colour=BLACK;
  439. right_rotate(parent[-1],par);
  440. x=tree->root;
  441. break;
  442.       }
  443.     }
  444.   }
  445.   x->colour=BLACK;
  446. }
  447. #ifdef TESTING_TREES
  448. /* Test that the proporties for a red-black tree holds */
  449. static int test_rb_tree(TREE_ELEMENT *element)
  450. {
  451.   int count_l,count_r;
  452.   if (!element->left)
  453.     return 0; /* Found end of tree */
  454.   if (element->colour == RED &&
  455.       (element->left->colour == RED || element->right->colour == RED))
  456.   {
  457.     printf("Wrong tree: Found two red in a rown");
  458.     return -1;
  459.   }
  460.   count_l=test_rb_tree(element->left);
  461.   count_r=test_rb_tree(element->right);
  462.   if (count_l >= 0 && count_r >= 0)
  463.   {
  464.     if (count_l == count_r)
  465.       return count_l+(element->colour == BLACK);
  466.     printf("Wrong tree: Incorrect black-count: %d - %dn",count_l,count_r);
  467.   }
  468.   return -1;
  469. }
  470. #endif