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