270 likes | 366 Views
Trees and beyond. Tutorial #3 CPSC 261. Trees are just an example. The next two weeks in labs we are playing with trees Trees are interesting Trees are not the only interesting data structure They are a good, first, simple data structure that uses pointers We could use lists, graphs, etc.
E N D
Trees and beyond Tutorial #3 CPSC 261
Trees are just an example • The next two weeks in labs we are playing with trees • Trees are interesting • Trees are not the only interesting data structure • They are a good, first, simple data structure that uses pointers • We could use lists, graphs, etc. • Trees fit the bill perfectly
What is a tree? • A directed, acyclic graph, where every node (except the root) has exactly one incoming edge
A binary tree • No node has more than 2 children
A “complete” binary tree • Every node has either 2 or 0 children • All leaves are at the same “level”
Node ordering • At their most general, trees assume nothing about the order of their nodes • Enforcing order provides value • Search trees • Binary search trees • Heaps • B-Trees
Thoughts about trees • They grow upside down (the root is at the top) • They are used for many purposes • A look-up structure • Sorting • Some of Java’s collection classes are trees • TreeSet • TreeMap
Trees in C • In C, we use structures like this to represent trees struct tree { sometype value; long nchildren; struct tree *children[MAXC]; }
Trees in C • Or in the case of binary trees struct tree { sometype value; struct tree *left, *right; } • Why no nchildren?
Traversing Trees in C – pre-order • Visiting all the nodes of a tree void visit(struct tree *t) { if (t == NULL) return; // do something with t->value visit(t->left); visit(t->right); }
Traversing Trees in C – in-order • Visiting all the nodes of a tree void visit(struct tree *t) { if (t == NULL) return; visit(t->left); // do something with t->value visit(t->right); }
Traversing Trees in C – post-order • Visiting all the nodes of a tree void visit(struct tree *t) { if (t == NULL) return; visit(t->left); visit(t->right); // do something with t->value }
Questions about visits • Will visit always terminate? • Why? • Will it visit every node? • Why? • Will it visit any node more than once? • Why?
Making trees • What kind of tree does this make? struct tree *makeTree(long levels) { if (levels <= 0) return NULL; struct tree *t = malloc (sizeof *t); t->value = random() % 1000; t->right = makeTree(levels - 1); t->left = makeTree(levels - 1); return t; }
Storing trees in files • Can you meaningfully store a value in a file? • Yes, if it is char, int, long, char * • Can you meaningfully store a pointer in a file? • Yes, but ... • What does it mean when you read it back? long *p; readPtr(infile, swap, &p); printf(“*p is %d\n”, *p); • Stack, heap are (likely) at a different address now than when the pointer was written to the file • *(long *) random() = 23;
Swizzling • “the conversion of references based on name or position to direct pointer references” [Wikipedia] • Performed when reading complex objects • Unswizzling is the opposite • Performed when writing complex objects
Here’s a tree, draw it • Each blue box represents 8 bytes • Draw the tree with circles, values and arrows 0x1230 37 0x1278 13 0x1238 left (0x1248) 0x1280 left (0x0) 0x1240 right (0x1260) 0x1288 right (0x0) 0x1248 25 0x1290 99 0x1250 left (0x1278) 0x1298 left (0x0) 0x1258 right (0x0) 0x12a0 right (0x0) 0x1260 52 0x1268 left (0x0) root 0x1230 0x1270 right (0x1290)
Circles and arrows 37 55 25 13 99
Don’t make assumptions • Tree nodes won’t be consecutive in memory • “Higher” nodes won’t have lower addresses 0x1230 37 0x1278 13 0x1238 left (0x1248) 0x1280 left (0x0) 0x1240 right (0x1260) 0x1288 right (0x0) 0x1248 25 0x1290 99 0x1250 left (0x1278) 0x1298 left (0x0) 0x1258 right (0x0) 0x12a0 right (0x0) 0x1260 52 0x1268 left (0x0) root 0x1230 0x1270 right (0x1290)
A file representation • Nodes have ids • Pointers have been converted to ids 5 1 3 37 52 99 left (2) left (0) left (0) right (3) right (5) right (0) 2 4 25 13 left (4) left (0) right (0) right (0)
Swizzling, how to convert? 5 1 3 37 52 99 left (2) left (0) left (0) right (3) right (5) right (0) 2 4 0x1230 37 0x1278 13 25 0x1238 13 left (0x1248) 0x1280 left (0x0) left (4) left (0) 0x1240 right (0x1260) 0x1288 right (0x0) right (0) right (0) 0x1290 0x1248 25 99 0x1250 left (0x1278) 0x1298 left (0x0) 0x1258 0x12a0 right (0x0) right (0x0) 0x1260 52 0x1268 left (0x0) 0x1270 right (0x1290)
Basic idea - reading Repeat Read an id (x) Allocate space for the node, call its address p Read the fields of *p Remember the mapping x -> p Until there is no more data in the file When reading data, you may need to swap bytes
After reading 1 -> 0xa330 2 -> 0xa348 3 -> 0xa360 4 -> 0xa378 5 -> 0xa390 0xa330 37 0xa378 13 0xa338 left (2) 0xa380 left (0) 0xa340 right (3) 0xa388 right (0) 0xa348 25 0xa390 99 0xa350 left (4) 0xa398 left (0) 0xa358 right (0) 0xa3a0 right (0) 0xa360 52 0xa368 left (0) root 1 0xa370 right (5)
Basic idea - swizzling For every entry in the table ( x -> p ) if p->left is not 0 new = lookup p->left in table p->left = new if p->right is not 0 new = lookup p->right in table p->right = new root = p from the first entry in the table
Afterswizzling 1 -> 0xa330 2 -> 0xa348 3 -> 0xa360 4 -> 0xa378 5 -> 0xa390 0xa330 37 0xa378 13 0xa338 left (0xa348) 0xa380 left (0x0) 0xa340 right (0xa360) 0xa388 right (0x0) 0xa348 25 0xa390 99 0xa350 left (0xa378) 0xa398 left (0x0) 0xa358 right (0x0) 0xa3a0 right (0x0) 0xa360 52 0xa368 left (0x0) root 0xa330 0xa370 right (0xa390)
Necessary type evil • new = lookup p->left in table • p->left has type struct tree * • table lookup expects an id (a long) • C casts convert between things • When the source and destination types of a cast are the same size (both 64 bits) and both “integer-like” the cast doesn’t modify any of the bits • (long)p->left