#include #include #include "treebuffer.h" struct Node { Node * parent; int data; // reference counter. A Node object can be deleted iff its // ref_count == 0 : int ref_count; // number of ancesters. Node.num_ancest == Node.parent->num_ancest + 1 int num_ancest; }; struct Tree { int history; Node * xs; // reference to the last added node Node * ys; // caterpillar }; /* ********** helper functions ********** */ // garbage collection ... void gc(Node * node) { if (node == NULL || node->ref_count > 0) return; Node * next = node->parent; free(node); if (next != NULL) { next->ref_count--; gc(next); } } /* ********** functions implements interfaces ********** */ Node * make_node(int data) { Node * node = (Node*)malloc(sizeof(Node)); node->parent = NULL; node->data = data; node->ref_count = 0; node->num_ancest = 0; return node; } int get_data(Node * node) { $assert(node, "attempt to get data from a invalid node reference"); return node->data; } Tree * empty(int history) { Tree * tree = (Tree*)malloc(sizeof(Tree)); tree->history = history; tree->xs = NULL; tree->ys = NULL; return tree; } Tree * add(Tree * tree, int data) { Node * node = make_node(data); Tree * new_tree = empty(tree->history); if (tree->xs == NULL) { new_tree->xs = node; new_tree->xs->ref_count++; new_tree->ys = tree->ys; if (tree->ys!=NULL) tree->ys->ref_count++; } else if(tree->xs->num_ancest < tree->history - 2) { node->parent = tree->xs; node->parent->ref_count++; node->num_ancest = node->parent->num_ancest + 1; new_tree->xs = node; new_tree->xs->ref_count++; new_tree->ys = tree->ys; if (tree->ys != NULL) new_tree->ys->ref_count++; } else { node->parent = tree->xs; node->parent->ref_count++; node->num_ancest = node->parent->num_ancest + 1; new_tree->ys = node; new_tree->ys->ref_count++; } return new_tree; } // Note: "ancestors" is an 0-terminated array: void take(Tree * tree, Node * ancestors[]) { int history = tree->history; int i = 0; Node * ancestor = tree->xs; while (i < history && ancestor != NULL) { ancestors[i++] = ancestor; ancestor = ancestor->parent; } ancestor = tree->ys; while (i < history && ancestor != NULL) { ancestors[i++] = ancestor; ancestor = ancestor->parent; } ancestors[i] = 0; } void delete(Tree * tree) { // took ys off and garbage collection: if (tree->ys != NULL) { Node * ys = tree->ys; tree->ys = NULL; ys->ref_count--; gc(ys); } if (tree->xs != NULL) { Node * xs = tree->xs; tree->xs = NULL; xs->ref_count--; gc(xs); } free(tree); }