|
|
@@ -0,0 +1,537 @@ |
|
|
/* simple int-valued AVL tree. Messy shitty code right now as I focused |
|
|
* on getting balancing working at all, lots of debug comments, and |
|
|
* 'height' is calculated as needed, not cached. But the balancing does |
|
|
* work. */ |
|
|
|
|
|
#include <assert.h> |
|
|
#include <stdio.h> |
|
|
#include <stdlib.h> |
|
|
#include "mine.h" |
|
|
|
|
|
typedef struct node { |
|
|
struct node *left, *right, *parent; |
|
|
int key, value; |
|
|
} Tree; |
|
|
|
|
|
int validate(const Tree * tree) ; |
|
|
int hvalidate(const Tree * tree) ; |
|
|
Tree* balinsert(Tree* tree, int key, int value) ; |
|
|
Tree* rotright(Tree* tree) ; |
|
|
Tree* rotleft(Tree* tree) ; |
|
|
|
|
|
Tree* insert(Tree* tree, int key, int value) { |
|
|
/* basic tree insertion. if a key already is present, the new value |
|
|
* is thrown away. The tree is returned. */ |
|
|
|
|
|
//assert(tree); |
|
|
if (!tree) { |
|
|
/*note this will mean a leaf node more often than an empty tree*/ |
|
|
Tree* node=0; |
|
|
node = calloc(1,sizeof(Tree)); |
|
|
if (!node) return NULL; |
|
|
node->key=key; |
|
|
node->value=value; |
|
|
return node; |
|
|
} else if (key == tree->key) { |
|
|
return tree; |
|
|
} else if (key < tree->key) { |
|
|
tree->left = insert(tree->left, key, value); |
|
|
tree->left->parent=tree; |
|
|
/* left might have been NUll, in which case we must set the parent |
|
|
* of the new node */ |
|
|
} else if (key > tree->key) { |
|
|
tree->right = insert(tree->right, key, value); |
|
|
tree->right->parent=tree; |
|
|
} |
|
|
return tree; |
|
|
} |
|
|
|
|
|
#define PREORDER -1 |
|
|
#define INORDER 0 |
|
|
#define POSTORDER 1 |
|
|
|
|
|
void traverse(const Tree* tree, int order) { |
|
|
// ordered traversals |
|
|
assert(tree); |
|
|
if (order == PREORDER) |
|
|
printf("key: %d, value %d, pointer %p\n",tree->key, tree->value, tree); |
|
|
if (tree->left) |
|
|
traverse(tree->left, order); |
|
|
if (order == INORDER) |
|
|
printf("key: %d, value %d, pointer %p\n",tree->key, tree->value, tree); |
|
|
//printf("key: %d, value %d\n",tree->key, tree->value); |
|
|
if (tree->right) |
|
|
traverse(tree->right, order); |
|
|
if (order == POSTORDER) |
|
|
printf("key: %d, value %d, pointer %p\n",tree->key, tree->value, tree); |
|
|
} |
|
|
|
|
|
int height(const Tree* tree) ; |
|
|
|
|
|
void printtree(const Tree* tree, int parent) { |
|
|
//special printer, with parent attribute for clarity |
|
|
//prints root on the right; nodes of same height are aligned |
|
|
//prints parent key, current key, height |
|
|
if (!tree) return; |
|
|
printtree(tree->left, tree->key); |
|
|
int _height=height(tree); |
|
|
for (int i=0;i<_height; i++) |
|
|
printf (" "); |
|
|
printf("%d:%d::%d\n",parent,tree->key,_height); |
|
|
printtree(tree->right, tree->key); |
|
|
} |
|
|
|
|
|
void printtree2(const Tree* tree, int depth, int parent) { |
|
|
//special printer, with parent attribute for clarity |
|
|
//n is number of spaces of indentation for tree levels |
|
|
//prints root on left; children are aligned |
|
|
//prints parent key, current key, depth |
|
|
if (!tree) return; |
|
|
printtree2(tree->right, depth+1, tree->key); |
|
|
for (int i=0;i<depth; i++) |
|
|
printf (" "); |
|
|
printf("%d:%d::%d\n",parent, tree->key, depth); |
|
|
printtree2(tree->left, depth+1, tree->key); |
|
|
} |
|
|
|
|
|
Tree* leftmost(Tree* tree) { |
|
|
if (tree->left) return leftmost(tree->left); |
|
|
else return tree; |
|
|
} |
|
|
|
|
|
Tree* rightmost(Tree* tree) { |
|
|
if (tree->right) return rightmost(tree->right); |
|
|
else return tree; |
|
|
} |
|
|
|
|
|
int height(const Tree* tree) { |
|
|
if (!tree) return 0; |
|
|
else { |
|
|
int lh=height(tree->left); |
|
|
int rh=height(tree->right); |
|
|
int h=max(lh,rh)+1; |
|
|
//printf("key %d lh %d rh %d h %d\n",tree->key, lh, rh, h); |
|
|
return h; |
|
|
} |
|
|
} |
|
|
|
|
|
Tree* lookup(Tree* tree, int key) { |
|
|
if (!tree) return NULL; |
|
|
else if (tree->key == key) return tree; |
|
|
else if (key < tree->key) return lookup(tree->left, key); |
|
|
else if (key > tree->key) return lookup(tree->right, key); |
|
|
assert(!"end of lookup"); |
|
|
} |
|
|
|
|
|
int leaf(const Tree* tree) { |
|
|
return (!tree->left) && (!tree->right); |
|
|
} |
|
|
|
|
|
#define ROOT 1 |
|
|
#define LEFT 2 |
|
|
#define RIGHT 3 |
|
|
|
|
|
int parenthood(const Tree* tree) { |
|
|
// are we root? if not, which child are we? |
|
|
if (tree->parent == NULL) return ROOT; |
|
|
else if (tree->parent->left == tree) return LEFT; |
|
|
else if (tree->parent->right == tree) return RIGHT; |
|
|
else assert(!"malformed tree in parenthood"); |
|
|
} |
|
|
|
|
|
int subtrees(const Tree* tree) { |
|
|
//how many subtrees? 0, 1, or 2 |
|
|
int subs=0; |
|
|
if (tree->left) subs++; |
|
|
if (tree->right) subs++; |
|
|
return subs; |
|
|
} |
|
|
|
|
|
Tree* trigger(Tree * tree) ; |
|
|
|
|
|
Tree* delete(Tree *tree, int key) { |
|
|
printf("delete: %d %d\n",tree->key, key); |
|
|
validate(tree); |
|
|
printtree(tree,0); |
|
|
Tree* tp=lookup(tree,key); |
|
|
if (!tp) return tree; |
|
|
if (leaf(tp)) { |
|
|
assert(subtrees(tp)==0); |
|
|
if (parenthood(tp) == ROOT) { |
|
|
// tree has only one node, which we are deleting |
|
|
//printf(" delete: %d %d\n",tree->key, tp->key); |
|
|
assert(tp==tree); |
|
|
validate(tree); |
|
|
free(tree); |
|
|
return 0; |
|
|
} |
|
|
else if (parenthood(tp) == LEFT) { |
|
|
tp->parent->left=NULL; |
|
|
} else { |
|
|
tp->parent->right=NULL; |
|
|
} |
|
|
free(tp); |
|
|
validate(tree); |
|
|
} // end if leaf |
|
|
else if (subtrees(tp) == 1) { |
|
|
//printf("trace on\n"); |
|
|
Tree* child=0; |
|
|
Tree* parent=tp->parent; |
|
|
if (tp->left) |
|
|
child=tp->left; |
|
|
else |
|
|
child=tp->right; |
|
|
//printf(" i\n"); |
|
|
//validate(tree); |
|
|
child->parent=parent; |
|
|
if (parenthood(tp)==LEFT) |
|
|
parent->left=child; |
|
|
else if (parenthood(tp)==RIGHT) |
|
|
parent->right=child; |
|
|
else { |
|
|
// deleting a root with one subtree |
|
|
//printf(" not off\n"); |
|
|
free(tp); |
|
|
//trigger(tree); |
|
|
return child; |
|
|
} |
|
|
//printf("tpk %d chkey %d park %d: trp %p tpp %p chp %p chpar %p parp %p parl %p parr %p\n",tp->key, child->key, parent->key, tree, tp, child, child->parent, parent, parent->left, parent->right); |
|
|
//printf(" 3\n"); |
|
|
memset(tp, 0, sizeof(Tree)); //debugging thing? |
|
|
free(tp); |
|
|
//validate(tree); |
|
|
//printf(" trace off\n"); |
|
|
//trigger(tree); |
|
|
//printf("trace off\n"); |
|
|
//validate(tree); |
|
|
} // end subtrees(tp) == 1 |
|
|
else { |
|
|
Tree* repl=rightmost(tp->left); |
|
|
tp->key=repl->key; |
|
|
tp->value=repl->value; |
|
|
delete(tp->left,repl->key); |
|
|
//tp->left=delete(tp->left,repl->key); |
|
|
|
|
|
//trigger(tree); // seems to make no difference |
|
|
} |
|
|
|
|
|
return tree; |
|
|
} |
|
|
|
|
|
// tree rotation functions. |
|
|
// rotation through the root needs to have the return value captured. |
|
|
Tree* oldrotright(Tree* tree) { |
|
|
// I thought this was so clever: rotate by pushing the root to the |
|
|
// right, copying up the rightmost left value, and deleting the |
|
|
// latter |
|
|
//printf("rotright 1\n"); |
|
|
//printtree(tree,0); |
|
|
//printf("rotright 2\n"); |
|
|
tree->right=balinsert(tree->right, tree->key, tree->value); |
|
|
tree->right->parent=tree; |
|
|
//printf(" %p %p %p\n",tree,tree->right, tree->right->parent); |
|
|
//printf(" %d %d %p\n",tree->key,tree->right->key, tree->left); |
|
|
//printtree(tree,0); |
|
|
//printf("rotright 3\n"); |
|
|
|
|
|
validate(tree); |
|
|
Tree* repl=rightmost(tree->left); |
|
|
//printf("rotright 4\n"); |
|
|
tree->key = repl->key; |
|
|
tree->value = repl->value; |
|
|
delete(tree->left, repl->key); |
|
|
trigger(tree->left); |
|
|
return tree; |
|
|
} |
|
|
Tree* oldrotleft(Tree* tree) { |
|
|
// I thought this was so clever: rotate by pushing the root to the |
|
|
// right, copying up the rightmost left value, and deleting the |
|
|
// latter |
|
|
//printf("rotright 1\n"); |
|
|
//printtree(tree,0); |
|
|
//printf("rotright 2\n"); |
|
|
tree->left=balinsert(tree->left, tree->key, tree->value); |
|
|
tree->left->parent=tree; |
|
|
//printf(" %p %p %p\n",tree,tree->right, tree->right->parent); |
|
|
//printf(" %d %d %p\n",tree->key,tree->right->key, tree->left); |
|
|
//printtree(tree,0); |
|
|
//printf("rotright 3\n"); |
|
|
|
|
|
validate(tree); |
|
|
Tree* repl=leftmost(tree->right); |
|
|
//printf("rotright 4\n"); |
|
|
tree->key = repl->key; |
|
|
tree->value = repl->value; |
|
|
delete(tree->right, repl->key); |
|
|
trigger(tree->right); |
|
|
return tree; |
|
|
} |
|
|
|
|
|
Tree* rotright(Tree* tree) { |
|
|
assert(tree->left); |
|
|
Tree* temp = tree; |
|
|
int parent = parenthood(tree); |
|
|
|
|
|
tree = temp->left; |
|
|
tree->parent = temp->parent; |
|
|
temp->left = tree->right; |
|
|
if (temp->left) |
|
|
temp->left->parent= temp; |
|
|
temp->parent = tree; |
|
|
tree->right = temp; |
|
|
|
|
|
if (parent == LEFT) |
|
|
tree->parent->left = tree; |
|
|
else if (parent == RIGHT) |
|
|
tree->parent->right = tree; |
|
|
|
|
|
//tree=trigger(tree->right); |
|
|
return tree; |
|
|
} |
|
|
|
|
|
Tree* rotleft(Tree* tree) { |
|
|
assert(tree->right); |
|
|
// printf("rotleft----\n"); |
|
|
// printtree2(tree,0,0); |
|
|
// printf("rotleft--\n"); |
|
|
Tree* temp = tree; |
|
|
int parent = parenthood(tree); |
|
|
|
|
|
tree = temp->right; |
|
|
tree->parent = temp->parent; |
|
|
temp->right = tree->left; |
|
|
if (temp->right) |
|
|
temp->right->parent= temp; |
|
|
temp->parent = tree; |
|
|
tree->left = temp; |
|
|
|
|
|
if (parent == LEFT) |
|
|
tree->parent->left = tree; |
|
|
else if (parent == RIGHT) |
|
|
tree->parent->right = tree; |
|
|
|
|
|
//trigger(tree->left); |
|
|
// printtree2(tree,0,0); |
|
|
// printf("rotleft----\n"); |
|
|
return tree; |
|
|
} |
|
|
|
|
|
/* not working |
|
|
Tree* _balinsert(Tree* tree, int key, int value) { |
|
|
if (!tree) |
|
|
return insert(tree,key, value); |
|
|
else if (key<tree->key) |
|
|
tree->left=balinsert(tree->left, key, value); |
|
|
else if (key>tree->key) |
|
|
tree->right=balinsert(tree->right, key, value); |
|
|
else return tree; |
|
|
|
|
|
int hl=height(tree->left); |
|
|
int hr=height(tree->right); |
|
|
if (hl-hr>1) rotright(tree); |
|
|
if (hl-hr<-1) rotleft(tree); |
|
|
printf("here %d %d %d\n",tree->key, hl, hr); |
|
|
return tree; |
|
|
} */ |
|
|
|
|
|
Tree* trigger(Tree * tree) { |
|
|
if (!tree) return tree; |
|
|
|
|
|
int hl=height(tree->left); |
|
|
int hr=height(tree->right); |
|
|
validate(tree); |
|
|
//printf("trigger 1: %d %d %d\n",tree->key, hl, hr); |
|
|
if (hl-hr>1) { |
|
|
int innerhr = height(tree->left->right); |
|
|
int sib_hl = height(tree->left->left); |
|
|
if (innerhr <= sib_hl) { |
|
|
tree=rotright(tree); |
|
|
tree->left->parent=tree; |
|
|
tree->right->parent=tree; |
|
|
} else { |
|
|
tree->left = rotleft(tree->left); |
|
|
tree = rotright(tree); |
|
|
tree->left->parent=tree; |
|
|
tree->right->parent=tree; |
|
|
} |
|
|
} |
|
|
else if (hl-hr<-1) { |
|
|
int innerhl = height(tree->right->left); |
|
|
int sib_hr = height(tree->right->right); |
|
|
if (innerhl <= sib_hr) { //simple |
|
|
tree=rotleft(tree); |
|
|
tree->left->parent=tree; |
|
|
tree->right->parent=tree; |
|
|
} else{ |
|
|
tree->right = rotright(tree->right); |
|
|
tree = rotleft(tree); |
|
|
tree->left->parent=tree; |
|
|
tree->right->parent=tree; |
|
|
} |
|
|
} |
|
|
//printf("trigger 2: %d %d %d\n",tree->key, hl, hr); |
|
|
//printtree2(tree,0,0); |
|
|
validate(tree); |
|
|
hvalidate(tree); |
|
|
//printf("trigger 4: %d %d %d\n",tree->key, hl, hr); |
|
|
return tree; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Tree* balinsert(Tree* tree, int key, int value) { |
|
|
//assert(tree); |
|
|
if (!tree) { |
|
|
Tree* node = calloc(1,sizeof(Tree)); |
|
|
if (!node) |
|
|
assert(!"calloc failure"); |
|
|
node->key=key; |
|
|
node->value=value; |
|
|
return node; |
|
|
} else if (key == tree->key) { |
|
|
return tree; |
|
|
} else if (key < tree->key) { |
|
|
tree->left = balinsert(tree->left, key, value); |
|
|
tree->left->parent=tree; |
|
|
//printf("valid l %d %p %p %p\n",tree->key,tree, tree->left,tree->left->parent); |
|
|
} else if (key > tree->key) { |
|
|
tree->right = balinsert(tree->right, key, value); |
|
|
tree->right->parent=tree; |
|
|
//printf("valid r %d %p %p %p\n",tree->key,tree, tree->right,tree->right->parent); |
|
|
} |
|
|
|
|
|
validate(tree); |
|
|
//printf("post valid %d\n",key); |
|
|
//printtree(tree,0); |
|
|
//printf("pre trigg %d\n",key); |
|
|
tree=trigger(tree); |
|
|
//printf("post trig 0 %d\n",key); |
|
|
validate(tree); |
|
|
hvalidate(tree); |
|
|
//printf("post trig 0 %d\n",key); |
|
|
// printf("pre valid %d\n",key); |
|
|
// validate(tree); |
|
|
//printf("post trigg %d\n",key); |
|
|
|
|
|
//printtree(tree,0); |
|
|
//printf("----\n"); |
|
|
//printf("here 2 %d %d %d\n",tree->key, hl, hr); |
|
|
//validate(tree); |
|
|
//printf("here 3 %d %d %d\n",tree->key, hl, hr); |
|
|
return tree; |
|
|
} |
|
|
|
|
|
int validate(const Tree * tree) { |
|
|
// makes sure all children and parents match |
|
|
if (!tree) return 1; |
|
|
int res=1; |
|
|
|
|
|
if (tree->left) { |
|
|
//printf("validleft %p %p %p\n",tree, tree->left, tree->left->parent); |
|
|
assert(tree->left->parent == tree); |
|
|
res&=validate(tree->left); |
|
|
} |
|
|
if (tree->right) { |
|
|
//printf("validright %p %p %p\n",tree, tree->right, tree->right->parent); |
|
|
assert(tree->right->parent == tree); |
|
|
res&=validate(tree->right); |
|
|
} |
|
|
return res; |
|
|
} |
|
|
|
|
|
int hvalidate(const Tree* tree){ |
|
|
if (!tree) return 1; |
|
|
int res=0; |
|
|
int hl=height(tree->left); |
|
|
int hr=height(tree->right); |
|
|
assert(abs(hl-hr)<=1); |
|
|
if (tree->left) |
|
|
res&=hvalidate(tree->left); |
|
|
if (tree->right) |
|
|
res&=hvalidate(tree->right); |
|
|
return res; |
|
|
} |
|
|
|
|
|
int main() { |
|
|
Tree* tree = 0; |
|
|
//tree->key=50; tree->value=11; |
|
|
//int keys[]= {50}; |
|
|
//int values[]={1}; |
|
|
// int keys[]= {1,2,3,4,5,6,7}; |
|
|
// int values[]={1,2,10,4,5,6,7}; |
|
|
//int values[]= {50,20,80,40,70,30,90,10,60, 35, 32, 55, 65, 45,20,19,18,17,16,15}; |
|
|
//int keys[]={1,2,3,4,5,6,7,8,9, 10, 11, 12, 13, 14,-20,-19,-18,-17,-16,-15}; |
|
|
int keys[]={1,2,3,4,5,6,7,8,9, 10, 11, 12, -13, 14, 15, 16, 17, 18, 19, |
|
|
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, -32, -33, -34}; |
|
|
int values[]={1,2,3,4,5,6,7,8,9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34}; |
|
|
|
|
|
for (int i=0; i< sizeof(keys)/sizeof(keys[0]); i++) { |
|
|
//printf("inserting step %d %d:%d\n",i, keys[i], values[i]); |
|
|
tree=balinsert(tree,keys[i],values[i]); |
|
|
validate(tree); |
|
|
hvalidate(tree); |
|
|
|
|
|
//printf("\n======= main loop \n"); |
|
|
//printtree(tree,0); |
|
|
//printf("-----\n"); |
|
|
//printtree2(tree,0,0); |
|
|
//printf("======= main loop end \n"); |
|
|
} |
|
|
printf("=======PRE\n"); |
|
|
traverse(tree, PREORDER); |
|
|
printf("=======1\n"); |
|
|
printtree(tree,0); |
|
|
printf("=======2\n"); |
|
|
printtree2(tree,0,0); |
|
|
printf("\n"); |
|
|
|
|
|
/* |
|
|
tree=rotleft(tree); |
|
|
|
|
|
printf("=======PRE\n"); |
|
|
traverse(tree, PREORDER); |
|
|
printf("=======1\n"); |
|
|
printtree(tree,0); |
|
|
printf("=======2\n"); |
|
|
printtree2(tree,0,0); |
|
|
printf("\n"); |
|
|
*/ |
|
|
|
|
|
/* |
|
|
traverse(tree, INORDER); |
|
|
printf("\n"); |
|
|
traverse(tree, POSTORDER); |
|
|
*/ |
|
|
//printf("%d\n",parenthood(lookup(tree, 90))); |
|
|
|
|
|
//delete(tree,40); |
|
|
//delete(tree,70); |
|
|
//tree=delete(tree,50); |
|
|
// rotleft(lookup(tree,5)); |
|
|
// rotleft(lookup(tree,9)); |
|
|
//rotleft(lookup(tree,8)); |
|
|
//rotleft(lookup(tree,8)); |
|
|
//rotright(lookup(tree,80)); |
|
|
//rotright(lookup(tree,70)); |
|
|
// validate(tree); |
|
|
// printf("====\n"); |
|
|
// printtree(tree,0); |
|
|
// printf("=======\n"); |
|
|
// printtree2(tree,0,0); |
|
|
//traverse(tree, PREORDER); |
|
|
//tree=rotright(tree); |
|
|
|
|
|
/* |
|
|
printf("look %d\n",lookup(tree,5)->value); |
|
|
printf("look %d\n",lookup(tree,1)->value); |
|
|
printf("look %d\n",lookup(tree,6)->value); |
|
|
Tree* tp= leftmost(tree); |
|
|
printf("%d, %d\n", tp->key, tp->value); |
|
|
tp=rightmost(tree); |
|
|
printf("%d, %d\n", tp->key, tp->value); |
|
|
|
|
|
printf("max 3 4 is %d\n",max(3,4)); |
|
|
printf("max 3 2 is %d\n",max(3,2)); |
|
|
printf("height tree is %d\n",height(tree)); |
|
|
*/ |
|
|
} |