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
;