ROSS
avl_tree.c
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <assert.h>
4 
5 /* Copied and modified from http://pine.cs.yale.edu/pinewiki/C/AvlTree google cache */
6 
7 #include "avl_tree.h"
8 
9 /* implementation of an AVL tree with explicit heights */
10 
12 
13 /* free a tree */
14 void
16 {
17  if (t != AVL_EMPTY) {
18  avlDestroy(t->child[0]);
19  t->child[0] = AVL_EMPTY;
20  avlDestroy(t->child[1]);
21  t->child[1] = AVL_EMPTY;
22  avl_free(t);
23  }
24 }
25 
26 /* return height of an AVL tree */
27 int
29 {
30  if (t != AVL_EMPTY) {
31  return t->height;
32  }
33  else {
34  return 0;
35  }
36 }
37 
38 /* return nonzero if key is present in tree */
39 int
41 {
42  if (t == AVL_EMPTY) {
43  return 0;
44  }
45 
46  if (TW_STIME_CMP(key->recv_ts, t->key->recv_ts) == 0) {
47  // Timestamp is the same
48  if (key->event_id == t->key->event_id) {
49  // Event ID is the same
50  if (key->send_pe == t->key->send_pe) {
51  // send_pe is the same
52  return 1;
53  }
54  else {
55  // send_pe is different
56  return avlSearch(t->child[key->send_pe > t->key->send_pe], key);
57  }
58  }
59  else {
60  // Event ID is different
61  return avlSearch(t->child[key->event_id > t->key->event_id], key);
62  }
63  }
64  else {
65  // Timestamp is different
66  return avlSearch(t->child[TW_STIME_CMP(key->recv_ts, t->key->recv_ts) > 0], key);
67  }
68 }
69 
70 /* assert height fields are correct throughout tree */
71 void
73 {
74  int i;
75 
76  if (root != AVL_EMPTY) {
77  for (i = 0; i < 2; i++) {
78  avlSanityCheck(root->child[i]);
79  }
80 
81  assert(root->height == 1 + ROSS_MAX(avlGetHeight(root->child[0]), avlGetHeight(root->child[1])));
82  }
83 }
84 
85 /* recompute height of a node */
86 static void
88 {
89  assert(t != AVL_EMPTY);
90 
91  t->height = 1 + ROSS_MAX(avlGetHeight(t->child[0]), avlGetHeight(t->child[1]));
92 }
93 
94 /* rotate child[d] to root */
95 /* assumes child[d] exists */
96 /* Picture:
97  *
98  * y x
99  * / \ <==> / \
100  * x C A y
101  * / \ / \
102  * A B B C
103  *
104  */
105 static void
106 avlRotate(AvlTree *root, int d)
107 {
108  AvlTree oldRoot;
109  AvlTree newRoot;
110  AvlTree oldMiddle;
111 
112  oldRoot = *root;
113  newRoot = oldRoot->child[d];
114  oldMiddle = newRoot->child[!d];
115 
116  oldRoot->child[d] = oldMiddle;
117  newRoot->child[!d] = oldRoot;
118  *root = newRoot;
119 
120  /* update heights */
121  avlFixHeight((*root)->child[!d]); /* old root */
122  avlFixHeight(*root); /* new root */
123 }
124 
125 
126 /* rebalance at node if necessary */
127 /* also fixes height */
128 static void
130 {
131  int d;
132 
133  if (*t != AVL_EMPTY) {
134  for (d = 0; d < 2; d++) {
135  /* maybe child[d] is now too tall */
136  if (avlGetHeight((*t)->child[d]) > avlGetHeight((*t)->child[!d]) + 1) {
137  /* imbalanced! */
138  /* how to fix it? */
139  /* need to look for taller grandchild of child[d] */
140  if (avlGetHeight((*t)->child[d]->child[d]) > avlGetHeight((*t)->child[d]->child[!d])) {
141  /* same direction grandchild wins, do single rotation */
142  avlRotate(t, d);
143  }
144  else {
145  /* opposite direction grandchild moves up, do double rotation */
146  avlRotate(&(*t)->child[d], !d);
147  avlRotate(t, d);
148  }
149 
150  return; /* avlRotate called avlFixHeight */
151  }
152  }
153 
154  /* update height */
155  avlFixHeight(*t);
156  }
157 }
158 
159 /* insert into tree */
160 /* this may replace root, which is why we pass
161  * in a AvlTree * */
162 void
164 {
165  /* insertion procedure */
166  if (*t == AVL_EMPTY) {
167  /* new t */
168  *t = avl_alloc();
169  if (*t == NULL) {
171  "AVL tree out of memory.\nIncrease avl-size beyond %d\n",
172  (int)log2(g_tw_avl_node_count));
173  }
174 
175  (*t)->child[0] = AVL_EMPTY;
176  (*t)->child[1] = AVL_EMPTY;
177 
178  (*t)->key = key;
179 
180  (*t)->height = 1;
181 
182  /* done */
183  return;
184  }
185 
186  if (TW_STIME_CMP(key->recv_ts, (*t)->key->recv_ts) == 0) {
187  // We have a timestamp tie, check the event ID
188  if (key->event_id == (*t)->key->event_id) {
189  // We have a event ID tie, check the send_pe
190  if (key->send_pe == (*t)->key->send_pe) {
191  // This shouldn't happen but we'll allow it
192  tw_printf(TW_LOC, "The events are identical!!!\n");
193  }
194  avlInsert(&(*t)->child[key->send_pe > (*t)->key->send_pe], key);
195  avlRebalance(t);
196  }
197  else {
198  // Event IDs are different
199  avlInsert(&(*t)->child[key->event_id > (*t)->key->event_id], key);
200  avlRebalance(t);
201  }
202  return;
203  }
204  else {
205  // Timestamps are different
206  avlInsert(&(*t)->child[TW_STIME_CMP(key->recv_ts, (*t)->key->recv_ts) > 0], key);
207  avlRebalance(t);
208  }
209 }
210 
211 
212 /* print all elements of the tree in order */
213 void
215 {
216  if (t != AVL_EMPTY) {
217  avlPrintKeys(t->child[0]);
218  //printf("%f\n", t->key->recv_ts);
219  avlPrintKeys(t->child[1]);
220  }
221 }
222 
223 
224 /* delete and return minimum value in a tree */
225 tw_event *
227 {
228  AvlTree oldroot;
229  tw_event *event_with_lowest_ts = NULL;
230 
231  assert(t != AVL_EMPTY);
232 
233  if ((*t)->child[0] == AVL_EMPTY) {
234  /* root is min value */
235  oldroot = *t;
236  event_with_lowest_ts = oldroot->key;
237  *t = oldroot->child[1];
238  avl_free(oldroot);
239  }
240  else {
241  /* min value is in left subtree */
242  event_with_lowest_ts = avlDeleteMin(&(*t)->child[0]);
243  }
244 
245  avlRebalance(t);
246  return event_with_lowest_ts;
247 }
248 
249 /* delete the given value */
250 tw_event *
252 {
253  tw_event *target = NULL;
254  AvlTree oldroot;
255 
256  if (*t == AVL_EMPTY) {
257  tw_error(TW_LOC, "We never look for non-existent events!");
258  return target;
259  }
260 
261  if (TW_STIME_CMP(key->recv_ts, (*t)->key->recv_ts) == 0) {
262  // We have a timestamp tie, check the event ID
263  if (key->event_id == (*t)->key->event_id) {
264  // We have a event ID tie, check the send_pe
265  if (key->send_pe == (*t)->key->send_pe) {
266  // This is actually the one we want to delete
267  target = (*t)->key;
268  /* do we have a right child? */
269  if ((*t)->child[1] != AVL_EMPTY) {
270  /* give root min value in right subtree */
271  (*t)->key = avlDeleteMin(&(*t)->child[1]);
272  }
273  else {
274  /* splice out root */
275  oldroot = (*t);
276  *t = (*t)->child[0];
277  avl_free(oldroot);
278  }
279  }
280  else {
281  // Timestamp and event IDs are the same, but different send_pe
282  target = avlDelete(&(*t)->child[key->send_pe > (*t)->key->send_pe], key);
283  }
284  }
285  else {
286  // Timestamps are the same but event IDs differ
287  target = avlDelete(&(*t)->child[key->event_id > (*t)->key->event_id], key);
288  }
289  }
290  else {
291  // Timestamps are different
292  target = avlDelete(&(*t)->child[TW_STIME_CMP(key->recv_ts, (*t)->key->recv_ts) > 0], key);
293  }
294 
295  avlRebalance(t);
296 
297  return target;
298 }
299 
301 {
302  AvlTree head = g_tw_pe->avl_list_head;
303  g_tw_pe->avl_list_head = head->next;
304 
305  if (g_tw_pe->avl_list_head == NULL) {
307  "AVL tree out of memory.\nIncrease avl-size beyond %d\n",
308  (int)log2(g_tw_avl_node_count));
309  }
310 
311  head->next = NULL;
312 
313  return head;
314 }
315 
317 {
318  (t)->child[0] = AVL_EMPTY;
319  (t)->child[1] = AVL_EMPTY;
320  (t)->next = NULL;
321  (t)->key = NULL;
322  (t)->height = 0;
323  (t)->next = g_tw_pe->avl_list_head;
324  g_tw_pe->avl_list_head = t;
325 }
#define TW_LOC
Definition: ross-extern.h:164
void avlInsert(AvlTree *t, tw_event *key)
Definition: avl_tree.c:163
void avl_free(AvlTree t)
Definition: avl_tree.c:316
int avlSearch(AvlTree t, tw_event *key)
Definition: avl_tree.c:40
void avlPrintKeys(AvlTree t)
Definition: avl_tree.c:214
tw_eventid event_id
Unique id assigned by src_lp->pe if remote.
Definition: ross-types.h:264
void tw_error(const char *file, int line, const char *fmt,...) NORETURN
Definition: tw-util.c:74
tw_event * avlDeleteMin(AvlTree *t)
Definition: avl_tree.c:226
tw_stime recv_ts
Actual time to be received.
Definition: ross-types.h:282
#define AVL_EMPTY
Definition: avl_tree.h:16
tw_event * avlDelete(AvlTree *t, tw_event *key)
Definition: avl_tree.c:251
Holds the entire PE state.
Definition: ross-types.h:375
tw_event * key
Definition: avl_tree.h:9
int avlGetHeight(AvlTree t)
Definition: avl_tree.c:28
static void avlRebalance(AvlTree *t)
Definition: avl_tree.c:129
static void avlFixHeight(AvlTree t)
Definition: avl_tree.c:87
Event Stucture.
Definition: ross-types.h:250
#define TW_STIME_CMP(x, y)
Definition: ross.h:154
uint32_t g_tw_avl_node_count
Definition: ross-global.c:37
void avlSanityCheck(AvlTree root)
Definition: avl_tree.c:72
AvlTree avl_alloc(void)
Definition: avl_tree.c:300
void avlDestroy(AvlTree t)
Definition: avl_tree.c:15
AvlTree avl_list_head
Definition: ross-types.h:392
tw_peid send_pe
Definition: ross-types.h:284
struct avlNode * next
Definition: avl_tree.h:11
tw_pe * g_tw_pe
Definition: ross-global.c:75
tw_pe * pe
Definition: avl_tree.c:11
#define ROSS_MAX(a, b)
static void avlRotate(AvlTree *root, int d)
Definition: avl_tree.c:106
int height
Definition: avl_tree.h:10
void tw_printf(const char *file, int line, const char *fmt,...)
Definition: tw-util.c:61
struct avlNode * child[2]
Definition: avl_tree.h:8