File:/home/sbrandt/cactus/Cactus/src/util/SKBinTree.c
1: /*@@
2:   @file      SKBinTree.c
3:   @date      Mon Oct  5 11:00:01 1998
4:   @author    Tom Goodale
5:   @desc
6:              Routines to deal with binary trees keyed by strings.
7:              The tree is a threaded tree, i.e. it can also be
8:              traversed, inorder, like a linked list.
9:   @enddesc
10:   @version   $Id: SKBinTree.c 3382 2003-08-22 11:21:37Z tradke $
11: @@*/
12:
13:#include <stdio.h>
14:#include <stdlib.h>
15:#include <string.h>
16:#include <ctype.h>
17:
18:#include "SKBinTree.h"
19:#include "util_String.h"
20:#include "cctk_Flesh.h"
21:
22:
23:static const char *rcsid = "$Header$";
24:
25:CCTK_FILEVERSION(util_SKBinTree_c);
26:
27: /*@@
28:   @routine    SKTreeStoreData
29:   @date       Mon Oct  5 11:04:55 1998
30:   @author     Tom Goodale
31:   @desc
32:   Stores data in string-keyed binary tree.
33:   @enddesc
34:@@*/
35:t_sktree *SKTreeStoreData(t_sktree *root, t_sktree *subtree,
36:                          const char *key, void *data)
37:{
38:  int order;
39:  t_sktree *newsubtree;
40:
41:  if(!subtree)
42:  {
43:    /* Create a new element. */
44:    newsubtree = (t_sktree *)malloc(sizeof(t_sktree));
45:    if(newsubtree)
46:    {
47:      newsubtree->left=NULL;
48:      newsubtree->right=NULL;
49:      newsubtree->next=NULL;
50:      newsubtree->last=NULL;
51:
52:      newsubtree->data = data;
53:
54:      newsubtree->key= (char *)malloc(sizeof(char)*(strlen(key)+1));
55:      strcpy(newsubtree->key, key);
56:      if(root)
57:      {
58:        if((order = Util_StrCmpi(key, root->key)) < 0)
59:        {
60:          root->left = newsubtree;
61:          newsubtree->next = root;
62:          newsubtree->last = root->last;
63:          if(newsubtree->last)
64:          {
65:            newsubtree->last->next = newsubtree;
66:          }
67:
68:          /*          printf("Added %s, NEXT: %s\n", newsubtree->key, root->key); */
69:        }
70:        else
71:        {
72:          root->right = newsubtree;
73:          newsubtree->next = root->next;
74:          newsubtree->last = root;
75:          root->next = newsubtree;
76:
77:          /*printf("Added %s, NEXT: %s\n", newsubtree->key, newsubtree->next ? newsubtree->next->key : "(none)");*/
78:          /*printf("Modified %s NEXT\n", root->key);*/
79:        }
80:
81:      }
82:    }
83:  }
84:  else
85:  {
86:    /* Go down left or right branch. */
87:    if((order = Util_StrCmpi(key, subtree->key)) < 0)
88:    {
89:      newsubtree = SKTreeStoreData(subtree, subtree->left, key, data);
90:    }
91:    else if(order > 0)
92:    {
93:      newsubtree = SKTreeStoreData(subtree, subtree->right, key, data);
94:    }
95:    else
96:    {
97:      /* Duplicate key. */
98:      newsubtree = NULL;
99:    }
100:
101:  }
102:
103:  /* Return either the new node, or NULL if either a duplicate value or
104:   * memory failure.
105:   */
106:
107:  return newsubtree;
108:
109:}
110:
111: /*@@
112:   @routine    SKTreeTraverseInorder
113:   @date       Mon Oct  5 11:05:54 1998
114:   @author     Tom Goodale
115:   @desc
116:   Traverse a tree 'inorder'
117:   @enddesc
118:@@*/
119:int SKTreeTraverseInorder(t_sktree *root, int (*process)(const char *, void *, void *), void *info)
120:{
121:  int terminate;
122:
123:  terminate = 0;
124:
125:  if(root)
126:  {
127:    terminate = SKTreeTraverseInorder(root->left, process, info);
128:    if(!terminate) terminate = process(root->key,root->data,info);
129:    if(!terminate) terminate = SKTreeTraverseInorder(root->right, process, info);
130:  }
131:
132:  return terminate;
133:}
134:
135: /*@@
136:   @routine    SKTreeTraversePreorder
137:   @date       Mon Oct  5 11:05:54 1998
138:   @author     Tom Goodale
139:   @desc
140:   Traverse a tree 'preorder'
141:   @enddesc
142:@@*/
143:int SKTreeTraversePreorder(t_sktree *root, int (*process)(const char *,void *, void *), void *info)
144:{
145:  int terminate;
146:
147:  terminate = 0;
148:
149:  if(root)
150:  {
151:    terminate = process(root->key,root->data, info);
152:    if(!terminate) terminate = SKTreeTraversePreorder(root->left, process, info);
153:    if(!terminate) terminate = SKTreeTraversePreorder(root->right, process,info);
154:  }
155:
156:  return terminate;
157:}
158:
159: /*@@
160:   @routine    SKTreeTraversePostorder
161:   @date       Mon Oct  5 11:05:54 1998
162:   @author     Tom Goodale
163:   @desc
164:   Traverse a tree 'postorder'
165:   @enddesc
166:@@*/
167:int SKTreeTraversePostorder(t_sktree *root, int (*process)(const char *, void *, void *), void *info)
168:{
169:  int terminate;
170:
171:  terminate = 0;
172:
173:  if(root)
174:  {
175:    terminate = SKTreeTraversePostorder(root->left, process, info);
176:    if(!terminate) terminate = SKTreeTraversePostorder(root->right, process, info);
177:    if(!terminate) terminate = process(root->key,root->data, info);
178:  }
179:
180:  return terminate;
181:}
182:
183: /*@@
184:   @routine    SKTreePrintNodes
185:   @date       Mon Oct  5 11:06:52 1998
186:   @author     Tom Goodale
187:   @desc
188:   Allows a binary tree to be printed out.
189:   @enddesc
190:@@*/
191:void SKTreePrintNodes(t_sktree *root, int depth, void (*print_node)(const char *,void *, int))
192:{
193:  if(root)
194:  {
195:    SKTreePrintNodes(root->left, depth+1,print_node);
196:    print_node(root->key,root->data,depth);
197:    SKTreePrintNodes(root->right, depth+1, print_node);
198:  }
199:}
200:
201:void SKTreeDebugNodes(t_sktree *root, int depth)
202:{
203:  if(root)
204:  {
205:    SKTreeDebugNodes(root->left, depth+1);
206:
207:    printf("KEY:   %s\n", root->key);
208:    printf("LEFT:  %s\n", root->left  ? root->left->key  : "(none)");
209:    printf("RIGHT: %s\n", root->right ? root->right->key : "(none)");
210:    printf("NEXT:  %s\n", root->next  ? root->next->key  : "(none)");
211:
212:    SKTreeDebugNodes(root->right, depth+1);
213:  }
214:}
215:
216:
217: /*@@
218:   @routine    SKTreeFindNode
219:   @date       Mon Jul  5 10:09:30 1999
220:   @author     Tom Goodale
221:   @desc
222:   Finds a given node in the tree.
223:   @enddesc
224:@@*/
225:t_sktree *SKTreeFindNode(t_sktree *root, const char *key)
226:{
227:  int order;
228:
229:  t_sktree *node;
230:
231:  if(root)
232:  {
233:    /* Go down left or right branch. */
234:    if((order = Util_StrCmpi(key, root->key)) < 0)
235:    {
236:      node = SKTreeFindNode(root->left, key);
237:    }
238:    else if(order > 0)
239:    {
240:      node = SKTreeFindNode(root->right, key);
241:    }
242:    else
243:    {
244:      /* Found it. */
245:      node = root;
246:    }
247:  }
248:  else
249:  {
250:    node = NULL;
251:  }
252:
253:  return node;
254:}
255:
256: /*@@
257:   @routine    SKTreeFindFirst
258:   @date       Mon Jul  5 10:09:57 1999
259:   @author     Tom Goodale
260:   @desc
261:   Finds the first node in the tree (the leftmost one).
262:   @enddesc
263:@@*/
264:t_sktree *SKTreeFindFirst(t_sktree *root)
265:{
266:  for(; root->left ; root = root->left);
267:
268:  return root;
269:}