#include #include #include "dict0.h" /************************************************************************/ TreeNode Dumbo; // volatile TreeNode *Dummy = &Dumbo; // a global dummy node #define ROTATELEFT tmp=t->right; t->right=tmp->left; tmp->left=t; t=tmp #define ROTATERIGHT tmp=t->left; t->left=tmp->right; tmp->right=t; t=tmp #define LINKLEFT tmp=t; t=t->right; l=l->right=tmp #define LINKRIGHT tmp=t; t=t->left; r=r->left=tmp #define ASSEMBLE r->left=t->right; l->right=t->left; \ t->left=Dummy->right; t->right=Dummy->left /************************************************************************/ /************************************************************************ Basic structure declarations from dict0.h: typedef struct tnode { struct tnode *left; // left child pointer struct tnode *right; // right child pointer void *item; // pointer to some structure } TreeNode; typedef struct dictnode { TreeNode *root; // pointer to the root of a SAT long size; // number of records in dictionary void * state; // reserved for state info // int (*cmp_rec)(void *, void *); comparison function pointer cmp_rec_func cmp_rec; TreeNode* (*splay)(TreeNode *, void *, cmp_rec_func); // pointer to a splay function void (*print_rec)(void *); // one line print function } Dictionary; #define DICT_CURR_ITEM(pDict) pDict->root->item typedef enum { SUCCESS, ITEM_ALREADY_PRESENT, ITEM_NOT_FOUND, FIRST_ITEM, LAST_ITEM, EMPTY_DICTIONARY, NULL_ITEM } Dict_Status; **************************************************************************/ /*************************************************************************/ /*** MIDL_user_allocate / MIDL_user_free ***/ /*************************************************************************/ void * MIDL_user_allocate(unsigned int count); void MIDL_user_free(void * p); /*************************************************************************/ /*** Minimal Dictionary Operations: ***/ /*** ***/ /*** Dictionary *Dict_New(Cmp_rec*, Splay*, print_rec*) ***/ /*** ***/ /*** Dict_Status Dict_Find(Dictionary*, Item*) ***/ /*** Dict_Status Dict_Next(Dictionary*, Item*) ***/ /*** Dict_Status Dict_Prev(Dictionary*, Item*) ***/ /*** Dict_Status Dict_Insert(Dictionary*, Item*) ***/ /*** Dict_Status Dict_Delete(Dictionary*, Item**) ***/ /*** ***/ /*** Item* DICT_CURR_ITEM(Dict*) ***/ /*************************************************************************/ #define TreeNode_New(pnode, pitem) pnode = \ (TreeNode*) MIDL_user_allocate (sizeof(TreeNode)); \ pnode->left = pnode->right = NULL; pnode->item = pitem; Dictionary* Dict_New( // returns a new dictionary node int (*cmp_rec) // pointer to item comparison function (void *, void *), TreeNode* (*splay) // pointer to a splay function (TreeNode *, void *, cmp_rec_func), void (*print_rec) // pointer to one line item print routine (void *) ) { Dictionary* dp; dp = (Dictionary*)MIDL_user_allocate(sizeof(Dictionary)); dp->root = NULL; dp->size = 0; dp->state = NULL; dp->print_rec = print_rec; dp->splay = splay; dp->cmp_rec = cmp_rec; return(dp); } Dict_Status Dict_Find( Dictionary* dp, // Dictionary to be searched. void* item) // Item searched for. { int keycmp; TreeNode* t; if (dp->root == NULL) return (EMPTY_DICTIONARY); if (item == NULL) return(NULL_ITEM); t = dp->root = dp->splay(dp->root, item, dp->cmp_rec); keycmp = (dp->cmp_rec)( t->item, item ); if (keycmp != 0) return(ITEM_NOT_FOUND); else return(SUCCESS); } Dict_Status Dict_Next( Dictionary* dp, // Dictionary to be searched. void* item) // A Key item. Advance to successor of item in dp. { TreeNode* t, *r; int keycmp; if (dp->root == NULL) return (EMPTY_DICTIONARY); if (item == NULL) { dp->root = tdSplayLeft(dp->root); return(SUCCESS); } if (item == DICT_CURR_ITEM(dp)) { t = dp->root; keycmp = 0; } else { dp->root = t = dp->splay(dp->root, item, dp->cmp_rec); keycmp = (dp->cmp_rec)( item, t->item ); } if (keycmp < 0) return(SUCCESS); else if (t->right == NULL) { return(LAST_ITEM); } else { t = dp->root; dp->root = tdSplayLeft(t->right); dp->root->left = t; t->right = NULL; return(SUCCESS); } } Dict_Status Dict_Prev( Dictionary* dp, // Dictionary to be searched. void* item) // A Key item. Retreat to predecessor of item in dp. { TreeNode* t, s; int keycmp; if (dp->root == NULL) return (EMPTY_DICTIONARY); if (item == NULL) { dp->root = tdSplayRight(dp->root); return(SUCCESS); } if (item == DICT_CURR_ITEM(dp)) { t = dp->root; keycmp = 0; } else { dp->root = t = dp->splay(dp->root, item, dp->cmp_rec); keycmp = (dp->cmp_rec)( item, t->item ); } if (keycmp > 0) return(SUCCESS); else if (t->left == NULL) { return(FIRST_ITEM); } else { t = dp->root; dp->root = tdSplayRight(t->left); dp->root->right = t; t->left = NULL; return(SUCCESS); } } Dict_Status Dict_Insert( // insert the given item into the tree Dictionary* dp, // the modified dictionary void* item) // the item to be inserted { int keycmp; TreeNode *t, *newNode; if (item == NULL) return(NULL_ITEM); if (dp->root == NULL) { TreeNode_New(newNode, item); dp->root = newNode; dp->size++; return(SUCCESS); } t = dp->root = dp->splay(dp->root, item, dp->cmp_rec); keycmp = (dp->cmp_rec)( t->item, item ); if (keycmp == 0) return(ITEM_ALREADY_PRESENT); TreeNode_New(newNode, item); if (keycmp < 0) { // t->item < item newNode->right = t->right; t->right = NULL; newNode->left = t; } else { newNode->left = t->left; t->left = NULL; newNode->right = t; } dp->root = newNode; dp->size++; return(SUCCESS); } Dict_Status Dict_Delete( // delete the given item into from the tree Dictionary* dp, // the modified dictionary void** pItem) // IN: points to the (key) item to be deleted // OUT: points to the item just deleted { TreeNode *t, *r; int keycmp; void* item = *pItem; t = dp->root; if (item == NULL) return(NULL_ITEM); if (dp->root == NULL) return (EMPTY_DICTIONARY); if (item == DICT_CURR_ITEM(dp)) keycmp = 0; else { dp->root = t = dp->splay(dp->root, item, dp->cmp_rec); keycmp = (dp->cmp_rec)( item, t->item ); } if (keycmp != 0) return(ITEM_NOT_FOUND); *pItem = DICT_CURR_ITEM(dp); if (t->left == NULL) { dp->root = t->right; } else if ( (r = t->right) == NULL) { dp->root = t->left; } else { r = tdSplayLeft(r); // at this point r->left == NULL r->left = t->left; dp->root = r; } t->left = t->right = t->item = NULL; MIDL_user_free(t); dp->size--; return(SUCCESS); } /*************************************************************************/ /***** Core functions (internal) *****/ /*************************************************************************/ TreeNode * // returns the new root tdSplay( // general top down splay TreeNode *root, // the current root of the tree void *keyItem, // pointer to a "key item" searched for int (*cmp)(void *, void *) ) // pointer to a comparison function { TreeNode* t=root; // current search point TreeNode* l; // root of "left subtree" < keyItem TreeNode* r; // root of "right subtree" > keyItem int kcmpt, kcmpleft, kcmpright; // cash comparison results TreeNode* tmp; /***/ Dummy = &Dumbo; l = Dummy; r = Dummy; /***/ if ( (root == NULL) || ((*cmp)(keyItem, root->item) == 0) ) return (root); Dummy->left=Dummy->right=NULL; while ( (kcmpt = (*cmp)(keyItem, t->item)) != 0 ) { if ( kcmpt < 0 ) { if ( t->left == NULL ) break; if ( (kcmpleft = (*cmp)(keyItem, t->left->item)) == 0 ) { LINKRIGHT; } else if ( kcmpleft < 0 ) { ROTATERIGHT; if ( t->left != NULL ) { LINKRIGHT; } } else { // keyItem > t->left->item LINKRIGHT; if ( t->right != NULL ) { LINKLEFT; } } } else { // keyItem > t->item if ( t->right == NULL ) break; if ( (kcmpright = (*cmp)(keyItem, t->right->item)) == 0 ) { LINKLEFT; } else if ( kcmpright > 0 ) { ROTATELEFT; if ( t->right != NULL ) { LINKLEFT; } } else { // keyItem < t->right->item LINKLEFT; if ( t->left != NULL ) { LINKRIGHT; } } } } // assemble: r->left=t->right; l->right=t->left; t->left=Dummy->right; t->right=Dummy->left; return(t); } TreeNode* tdSplayLeft(TreeNode* root) { TreeNode* t=root; // current "search" point TreeNode* l=Dummy; // root of "left subtree" < keyItem TreeNode* r=Dummy; // root of "right subtree" > keyItem TreeNode* tmp; if ((t == NULL) || (t->left == NULL)) return(t); if (t->left->left == NULL) { ROTATERIGHT; return(t); } Dummy->left=Dummy->right=NULL; while ( t->left != NULL ) { ROTATERIGHT; if ( t->left != NULL ) { LINKRIGHT; } } r->left=t->right; l->right=t->left; t->left=Dummy->right; t->right=Dummy->left; return(t); } TreeNode* tdSplayRight(TreeNode* root) { TreeNode* t=root; // current "search" point TreeNode* l=Dummy; // root of "left subtree" < keyItem TreeNode* r=Dummy; // root of "right subtree" > keyItem TreeNode* tmp; if ((t == NULL) || (t->right == NULL)) return(t); Dummy->left=Dummy->right=NULL; while ( t->right != NULL ) { ROTATELEFT; if ( t->right != NULL ) { LINKLEFT; } } r->left=t->right; l->right=t->left; t->left=Dummy->right; t->right=Dummy->left; return(t); }