/* * Caolan.McNamara@ul.ie * http://www.csn.ul.ie/~caolan * * Released under the GPL, see COPYING */ #include #include #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "bintree.h" #include "wv.h" void InitBintree (BintreeInfo * tree, int (*func1) (void *, void *), int (*func2) (void *, void *)) { tree->Root = NULL; /* root of binary tree */ tree->no_in_tree = 0; tree->CompLT = func1; tree->CompEQ = func2; } Node * InsertNode (BintreeInfo * tree, void *Data) { Node *X, *Current, *Parent; /*********************************************** * allocate node for Data and insert in tree * ***********************************************/ /* find X's parent */ Current = tree->Root; Parent = 0; while (Current) { if (tree->CompEQ (Data, Current->Data)) return (NULL); Parent = Current; Current = tree->CompLT (Data, Current->Data) ? Current->Left : Current->Right; } /* setup new node */ if ((X = (Node *) wvMalloc (sizeof (Node))) == 0) { fprintf (stderr, "insufficient memory (InsertNode)\n"); exit (1); } tree->no_in_tree++; X->Data = Data; X->Parent = Parent; X->Left = NULL; X->Right = NULL; /* insert X in tree */ if (Parent) { if (tree->CompLT (Data, Parent->Data)) Parent->Left = X; else Parent->Right = X; } else tree->Root = X; return (X); } void wvDeleteNode (BintreeInfo * tree, Node * Z) { Node *X, *Y; /***************************** * delete node Z from tree * *****************************/ /* Y will be removed from the parent chain */ if (!Z || Z == NULL) return; tree->no_in_tree--; /* find tree successor */ if (Z->Left == NULL || Z->Right == NULL) Y = Z; else { Y = Z->Right; while (Y->Left != NULL) Y = Y->Left; } /* X is Y's only child */ if (Y->Left != NULL) X = Y->Left; else X = Y->Right; /* remove Y from the parent chain */ if (X) X->Parent = Y->Parent; if (Y->Parent) { if (Y == Y->Parent->Left) Y->Parent->Left = X; else Y->Parent->Right = X; } else tree->Root = X; /* Y is the node we're removing */ /* Z is the data we're removing */ /* if Z and Y are not the same, replace Z with Y. */ if (Y != Z) { Y->Left = Z->Left; if (Y->Left) Y->Left->Parent = Y; Y->Right = Z->Right; if (Y->Right) Y->Right->Parent = Y; Y->Parent = Z->Parent; if (Z->Parent) { if (Z == Z->Parent->Left) Z->Parent->Left = Y; else Z->Parent->Right = Y; } else tree->Root = Y; wvFree (Z); } else { wvFree (Y); } } Node * FindNode (BintreeInfo * tree, void *Data) { /******************************* * find node containing Data * *******************************/ Node *Current = tree->Root; while (Current != NULL) if (tree->CompEQ (Data, Current->Data)) return (Current); else Current = tree->CompLT (Data, Current->Data) ? Current->Left : Current->Right; return (0); } Node * NextNode (BintreeInfo * tree, Node * element) { Node *father_of_element; Node *father_of_forefather; if (!element) { father_of_element = tree->Root; if (father_of_element != NULL) while (father_of_element->Left != NULL) father_of_element = father_of_element->Left; } else { father_of_element = element; if (father_of_element->Right != NULL) { father_of_element = father_of_element->Right; while (father_of_element->Left != NULL) father_of_element = father_of_element->Left; } else { father_of_forefather = father_of_element->Parent; while (father_of_forefather && (father_of_forefather->Right == father_of_element)) { father_of_element = father_of_forefather; father_of_forefather = father_of_element->Parent; } father_of_element = father_of_forefather; } } return father_of_element; }