ZEDA  1.6.18
zeda_tree.h
Go to the documentation of this file.
1 /* ZEDA - Elementary Data and Algorithms
2  * Copyright (C) 1998 Tomomichi Sugihara (Zhidao)
3  */
9 #ifndef __ZEDA_TREE_H__
10 #define __ZEDA_TREE_H__
11 
12 #include <zeda/zeda_misc.h>
13 
15 
16 /* ********************************************************** *//* ************************************************** */
19 
20 /* ********************************************************** *//* ******************************************************* */
40 
41 #define zTreeClass(node_t,data_t) \
42 typedef struct __##node_t{\
43  struct __##node_t *parent;\
44  struct __##node_t *child[2];\
45  uint size;\
46  data_t data;\
47 } node_t;\
48 \
49 __EXPORT node_t *node_t##Init(node_t *node);\
50 __EXPORT void node_t##Destroy(node_t *tree);\
51 __EXPORT node_t *node_t##NodeAlloc(data_t *val)
52 
53 #define zTreeClassMethod(node_t,data_t,init,destroy) \
54 static data_t *(* _##node_t##DataInit)(data_t *) = init;\
55 static void (* _##node_t##DataDestroy)(data_t *) = destroy;\
56 \
57 node_t *node_t##Init(node_t *node){\
58  if( _##node_t##DataInit ) _##node_t##DataInit( &(node)->data );\
59  node->parent = node->child[0] = node->child[1] = NULL;\
60  node->size = 0;\
61  return node;\
62 }\
63 \
64 static void __##node_t##NodeDestroy(node_t *node){\
65  if( node->child[0] )\
66  __##node_t##NodeDestroy( node->child[0] );\
67  if( node->child[1] )\
68  __##node_t##NodeDestroy( node->child[1] );\
69  if( _##node_t##DataDestroy ) _##node_t##DataDestroy( &(node)->data );\
70  free( node );\
71 }\
72 \
73 void node_t##Destroy(node_t *tree){\
74  if( tree->child[0] )\
75  __##node_t##NodeDestroy( tree->child[0] );\
76  node_t##Init( tree );\
77 }\
78 \
79 node_t *node_t##NodeAlloc(data_t *val){\
80  node_t *node;\
81  if( !( node = zAlloc( node_t, 1 ) ) ){\
82  ZALLOCERROR();\
83  return NULL;\
84  }\
85  node_t##Init( node );\
86  memcpy( &node->data, val, sizeof(data_t) );\
87  return node;\
88 }
89 
90 #define zHeapClass(node_t,data_t) \
91 zTreeClass(node_t,data_t); \
92 __EXPORT node_t *node_t##AddComplete(node_t *tree, data_t *val);\
93 __EXPORT node_t *node_t##UpHeap(node_t *tree, node_t *node, int (* cmp)(node_t*,node_t*,void*), void *util);\
94 __EXPORT node_t *node_t##AddHeap(node_t *tree, data_t *val, int (* cmp)(node_t*,node_t*,void*), void *util);\
95 __EXPORT node_t *node_t##DownHeap(node_t *node, int (* cmp)(node_t*,node_t*,void*), void *util);\
96 __EXPORT node_t *node_t##DeleteHeap(node_t *tree, int (* cmp)(node_t*,node_t*,void*), void *util);\
97 __EXPORT void node_t##Heapify(node_t *tree, int (* cmp)(node_t*,node_t*,void*), void *util)
98 
99 #define zHeapClassMethod(node_t,data_t,init,destroy) \
100 zTreeClassMethod(node_t,data_t,init,destroy) \
101 static void __##node_t##BindParentChild(node_t *parent, int id, node_t *child){\
102  if( ( parent->child[id] = child ) ) child->parent = parent;\
103 }\
104 \
105 static void __##node_t##NodeSwapHeap(node_t *node, int cid){\
106  node_t *parent, *tmp;\
107  int id;\
108  parent = node->parent;\
109  id = _zTreeParentID( node );\
110  __##node_t##BindParentChild( parent, id, node->child[cid] );\
111  __##node_t##BindParentChild( node, cid, node->child[cid]->child[cid] );\
112  __##node_t##BindParentChild( parent->child[id], cid, node );\
113  tmp = node->child[1-cid];\
114  __##node_t##BindParentChild( node, 1-cid, parent->child[id]->child[1-cid] );\
115  __##node_t##BindParentChild( parent->child[id], 1-cid, tmp );\
116 }\
117 \
118 node_t *node_t##AddComplete(node_t *tree, data_t *val){\
119  node_t *node, *np_new;\
120  uint mask, cid;\
121  if( !( np_new = node_t##NodeAlloc( val ) ) ) return NULL;\
122  if( ++tree->size == 1 ){\
123  __##node_t##BindParentChild( tree, 0, np_new );\
124  return tree->child[0];\
125  }\
126  _zTreeInitHeapMask( tree, &mask );\
127  for( node=tree->child[0]; ; node=node->child[cid], mask>>=1 ){\
128  cid = mask & tree->size ? 1 : 0;\
129  if( mask == 1 ) break;\
130  }\
131  __##node_t##BindParentChild( node, cid, np_new );\
132  return np_new;\
133 }\
134 \
135 node_t *node_t##UpHeap(node_t *tree, node_t *node, int (* cmp)(node_t*,node_t*,void*), void *util){\
136  while( node->parent != tree && !cmp( node->parent, node, util ) )\
137  __##node_t##NodeSwapHeap( node->parent, _zTreeParentID( node ) );\
138  return node;\
139 }\
140 \
141 node_t *node_t##AddHeap(node_t *tree, data_t *val, int (* cmp)(node_t*,node_t*,void*), void *util){\
142  return node_t##UpHeap( tree, node_t##AddComplete( tree, val ), cmp, util );\
143 }\
144 \
145 node_t *node_t##DownHeap(node_t *node, int (* cmp)(node_t*,node_t*,void*), void *util){\
146  uint cid;\
147  while( node->child[0] ){\
148  cid = !node->child[1] ? 0 : ( cmp( node->child[0], node->child[1], util ) ? 0 : 1 );\
149  if( cmp( node, node->child[cid], util ) ) break;\
150  __##node_t##NodeSwapHeap( node, cid );\
151  }\
152  return node;\
153 }\
154 \
155 node_t *node_t##DeleteHeap(node_t *tree, int (* cmp)(node_t*,node_t*,void*), void *util){\
156  node_t *ret, *np;\
157  uint mask, cid;\
158  _zTreeInitHeapMask( tree, &mask );\
159  for( np=tree->child[0]; np; mask>>=1, np=np->child[cid] ){\
160  cid = mask & tree->size ? 1 : 0;\
161  if( mask == 1 ) break;\
162  }\
163  ret = tree->child[0];\
164  if( !np ){\
165  tree->child[0] = NULL;\
166  } else if( np->child[cid] ){\
167  __##node_t##BindParentChild( tree, 0, np->child[cid] );\
168  np->child[cid] = NULL;\
169  __##node_t##BindParentChild( tree->child[0], 0, ret->child[0] );\
170  __##node_t##BindParentChild( tree->child[0], 1, ret->child[1] );\
171  node_t##DownHeap( tree->child[0], cmp, util );\
172  }\
173  ret->parent = ret->child[0] = ret->child[1] = NULL;\
174  tree->size--;\
175  return ret;\
176 }\
177 \
178 static void __##node_t##Heapify(node_t *tree, int (* cmp)(node_t*,node_t*,void*), void *util){\
179  if( zTreeIsLeaf( tree ) ) return;\
180  if( tree->child[0] ) __##node_t##Heapify( tree->child[0], cmp, util );\
181  if( tree->child[1] ) __##node_t##Heapify( tree->child[1], cmp, util );\
182  node_t##DownHeap( tree, cmp, util );\
183 }\
184 \
185 void node_t##Heapify(node_t *tree, int (* cmp)(node_t*,node_t*,void*), void *util){\
186  if( zTreeIsEmpty( tree ) ) return;\
187  __##node_t##Heapify( tree->child[0], cmp, util );\
188 }
189 
190 #define zTreeIsEmpty(t) ( (t)->size == 0 )
191 #define zTreeIsLeaf(t) ( !(t)->child[0] && !(t)->child[1] )
192 
193 #define _zTreeParentID(n) ( (n)->parent->child[0] == (n) ? 0 : ( (n)->parent->child[1] == (n) ? 1 : -1 ) )
194 
195 #define _zTreeInitHeapMask(t,mask) do{\
196  *(mask) = 1 << ( sizeof(int)*8 - 2 );\
197  while( !( *(mask) & (t)->size ) ) *(mask) >>= 1;\
198  *(mask) >>= 1;\
199 } while(0)
200 
201 #define zTreeInit(node_t,node) node_t##Init( node )
202 #define zTreeDestroy(node_t,tree) node_t##Destroy( tree )
203 #define zTreeNodeAlloc(node_t,val) node_t##NodeAlloc( val )
204 #define zTreeAddComplete(node_t,tree,val) node_t##AddComplete( tree, val )
205 #define zTreeUpHeap(node_t,tree,node,cmp,util) node_t##UpHeap( tree, node, cmp, util )
206 #define zTreeAddHeap(node_t,tree,val,cmp,util) node_t##AddHeap( tree, val, cmp, util )
207 #define zTreeDownHeap(node_t,node,cmp,util) node_t##DownHeap( node, cmp, util )
208 #define zTreeDeleteHeap(node_t,tree,cmp,util) node_t##DeleteHeap( tree, cmp, util )
209 #define zTreeHeapify(node_t,tree,cmp,util) node_t##Heapify( tree, cmp, util )
210 
214 
215 #endif /* __ZEDA_TREE_H__ */
#define __END_DECLS
Definition: zeda_defs.h:30
miscellanies.
#define __BEGIN_DECLS
Definition: zeda_defs.h:26