2 scm-bintree.cc -- implement binary trees, an experiment in GC.
4 source file of the GNU LilyPond music typesetter
6 (c) 1999 Han-Wen Nienhuys <hanwen@cs.uu.nl>
11 #include "libc-extension.hh"
12 #include "lily-guile.hh"
22 (key . (left_child . right_child))
24 SCM_EOL is the nil-pointer (should use SCM_NIMP() ?)
27 #define left_child(s) SCM_CADR((s))
28 #define right_child(s) SCM_CDDR((s))
29 #define key(s) SCM_CAR((s))
32 Garble pointers, to prevent unbalanced tree due to ordered inserts.
39 return (unsigned int)(s << (32-SHIFT) | s >> SHIFT );
43 ly_new_bintree_node (SCM val)
45 return gh_cons (val, gh_cons (SCM_EOL, SCM_EOL));
50 add VAL to TREE. TREE must be non-nil
53 ly_addto_bintree (SCM *tree, SCM val)
55 while(*tree != SCM_EOL)
57 if (munge (val) <= munge (key (*tree)))
58 tree = &left_child (*tree);
60 tree = &right_child (*tree);
63 *tree = ly_new_bintree_node (val);
68 find the address of a node in the tree represented by *NODE with key VAL
71 ly_find_in_bintree (SCM *node, SCM val)
73 while (*node != SCM_EOL)
75 if (munge (val) < munge (key(*node) ))
76 node = &left_child(*node);
77 else if (munge (val) > munge (key (*node)))
78 node = &right_child (*node);
86 ly_remove_from_bintree (SCM *node)
88 SCM r = right_child (*node);
89 SCM l = left_child (*node);
95 else if (l == SCM_EOL)
101 /*deleting from binary trees. See Knuth's TAOCP.
104 SCM *left_t = &left_child (*t);
107 INV: LEFT_T is the left child of T
109 while (*left_t != SCM_EOL)
112 left_t = &left_child (*t);
116 POST: T is the leftmost right child of NODE which has no left child,
118 leftchild (LASTT) == T
120 key(*node) = key(*t);
121 *left_t = right_child (*t);
126 static SCM protect_tree_root;
129 ly_protect_scm (SCM s)
131 ly_addto_bintree (&protect_tree_root, s);
136 ly_unprotect_scm (SCM s)
138 SCM *to_remove = ly_find_in_bintree (&protect_tree_root, s);
141 this shouldn't happen, according to me. But it does.
143 if (*to_remove != SCM_EOL)
144 ly_remove_from_bintree (to_remove);
149 ly_init_protection ()
151 protect_tree_root = scm_protect_object (ly_new_bintree_node(SCM_EOL));
152 key (protect_tree_root) = protect_tree_root;
157 ly_count_elements (SCM tree)
162 return 1 + ly_count_elements (left_child (tree)) + ly_count_elements (right_child( tree));
166 ly_tree_depth (SCM tree)
171 return 1 + (ly_tree_depth (left_child (tree)) >? ly_tree_depth (right_child(tree)));
175 ly_print_bintree (SCM node)
180 DOUT << "{val = " << key(node) << " \nleft = ";
181 ly_print_bintree (left_child (node));
182 DOUT << "\n right =";
183 ly_print_bintree (right_child (node));
189 struct Imbalance { int imbalance; int total; };
192 ly_calc_imbalance (SCM node)
202 Imbalance l = ly_calc_imbalance (left_child (node));
203 Imbalance r = ly_calc_imbalance (right_child (node));
205 t.total = l.total + r.total + 1;
206 int dif = l.total - r.total;
209 t.imbalance = l.imbalance + r.imbalance + dif;