diff --git a/PA08-1101/PA08_Main b/PA08-1101/PA08_Main new file mode 100755 index 0000000..2a663c2 Binary files /dev/null and b/PA08-1101/PA08_Main differ diff --git a/PA08-1101/RedBlackTreeUtility.c b/PA08-1101/RedBlackTreeUtility.c index f4fa8f0..d064cb2 100644 --- a/PA08-1101/RedBlackTreeUtility.c +++ b/PA08-1101/RedBlackTreeUtility.c @@ -6,9 +6,616 @@ const char SEMICOLON_BREAK[] = "; "; const char THICK_DIVIDER = '='; const char THIN_DIVIDER = '-'; +/* Data Structures +typedef struct RedBlackNodeStruct + { + Colors color; (typedef enum { BLACK = 66, RED = 82 } Colors;) + + char data; + + struct RedBlackNodeStruct *parentPtr, *leftChildPtr, *rightChildPtr; + + } RedBlackNodeType; + +typedef enum { PREORDER_TRAVERSE = 101, INORDER_TRAVERSE = 102, + POSTORDER_TRAVERSE = 103, NODE_COLOR = 191, + NODE_DATA = 192 } ControlCodes; +Data Structures */ + // functions -// TODO: Set functions here +/* +Name: clearTree +Process: recursively returns dynamically allocated data to the OS + using a post order traversal strategy +Function input/parameters: working pointer for recursion (RedBlackNodeType *) +Function output/parameters: none +Function output/returned: empty tree (NULL) +Device input/---: none +Device output/---: none +Dependencies: free +*/ +RedBlackNodeType *clearTree(RedBlackNodeType *localPtr) +{ + // recurse through the left children + if (localPtr->leftChildPtr != NULL) + { + clearTree(localPtr->leftChildPtr); + } + // recurse through the right children + if (localPtr->rightChildPtr != NULL) + { + clearTree(localPtr->rightChildPtr); + } + // otherwise, free the local pointer if at end of getting to bottom tree + free(localPtr); + // return NULL since no tree left + return NULL; +} + +/* +Name: copyTree +Process: copies a Red Black tree from another Red Black tree + using a pre order traversal strategy, + appropriately links child parent pointers to current node +Function input/parameters: pointer to source node (RedBlackNodeType *) +Function output/parameters: none +Function output/returned: pointer to destination node (RedBlackNodeType *) +Device input/---: none +Device output/---: none +Dependencies: createNodeFromNode, copyTree (recursively) +*/ +RedBlackNodeType *copyTree(RedBlackNodeType *srcPtr) +{ + // make a storage pointer + RedBlackNodeType *copyPtr = NULL; + // check for not equal to null + if (srcPtr != NULL) + { + // create the pointer given data + copyPtr = createNodeFromNode(srcPtr); + // recurse left child + copyPtr->leftChildPtr = copyTree(srcPtr->leftChildPtr); + // recurse right child + copyPtr->rightChildPtr = copyTree(srcPtr->rightChildPtr); + } + // return copyPtr + return copyPtr; +} + +/* +Name: createNodeFromData +Process: creates a Red Black tree node from the node data given, + all links are set to NULL +Function input/parameters: data (char), color (int) +Function output/parameters: none +Function output/returned: pointer to created node (RedBlackNodeType *) +Device input/---: none +Device output/---: none +Dependencies: malloc +*/ +RedBlackNodeType *createNodeFromData(char data, int nodeColor) +{ + // define a new node + RedBlackNodeType *newNode; + // allocate memory for the newNode (RedBlackNodeType) + newNode = malloc(sizeof(RedBlackNodeType)); + // define the color as the new node's color + newNode->color = nodeColor; + // define the data of the new node to be the input data + newNode->data = data; + // set the node's pointers according to spec + newNode->parentPtr = NULL; + newNode->leftChildPtr = NULL; + newNode->rightChildPtr = NULL; + // return the created node + return newNode; +} + +/* +Name: createNodeFromNode +Process: allocates memory for node, + copies an individual tree node from another node, + all links are set to NULL +Function input/parameters: pointer to source node (RedBlackNodeType *) +Function output/parameters: none +Function output/returned: pointer to destination node (RedBlackNodeType *) +Device input/---: none +Device output/---: none +Dependencies: one line of code - createNodeFromData +*/ +RedBlackNodeType *createNodeFromNode(RedBlackNodeType *srcPtr) +{ + // return the created node from the given data + return createNodeFromData(srcPtr->data, srcPtr->color); +} + +/* +Name: displayInOrder +Process: traverses across tree, prints semicolon-delimited list, + displays "data / color" using in order strategy +Function input/parameters: pointer to current working node (RedBlackNodeType *), + pointer to row start flag + for first line of output (bool *) +Function output/parameters: none +Function output/returned: none +Device input/---: none +Device output/---: displayed as specified +Dependencies: printf, displayInOrder (recursively) +*/ +void displayInOrder(RedBlackNodeType *wkgPtr, bool *rowStartFlag) +{ + // check to see if the working pointer is null + if (wkgPtr != NULL) + { + // check to see if the rowStartFlag is true + if(rowStartFlag) + { + // if true, print the order + printf("Inorder : "); + // set the rowStartFlag to false + rowStartFlag = false; + } + // recurse to left node in tree + displayInOrder(wkgPtr->leftChildPtr, rowStartFlag); + // print out the string + printf(" %c/%c%s", wkgPtr->data, wkgPtr->color, SEMICOLON_BREAK); + // recurse to right node in tree + displayInOrder(wkgPtr->rightChildPtr, rowStartFlag); + } + // no return, void. +} + +/* +Name: displayPostOrder +Process: traverses across tree, prints semicolon-delimited list, + displays "data / color" using post order strategy +Function input/parameters: pointer to current working node (RedBlackNodeType *), + pointer to row start flag + for first line of output (bool *) +Function output/parameters: none +Function output/returned: none +Device input/---: none +Device output/---: displayed as specified +Dependencies: printf, displayPostOrder (recursively) +*/ +void displayPostOrder(RedBlackNodeType *wkgPtr, bool *rowStartFlag) +{ + // check to see if the working pointer is null + if (wkgPtr != NULL) + { + // check to see if the rowStartFlag is true + if (rowStartFlag) + { + // if true, print the order + printf("Postorder: "); + // set the rowStartFlag to false + rowStartFlag = false; + } + // recurse to left node in tree + displayPostOrder(wkgPtr->leftChildPtr, rowStartFlag); + // recurse to right node in tree + displayPostOrder(wkgPtr->rightChildPtr, rowStartFlag); + // print out the string + printf(" %c/%c%s", wkgPtr->data, wkgPtr->color, SEMICOLON_BREAK); + } + // no return, void. +} + +/* +Name: displayPreOrder +Process: traverses across tree, prints semicolon-delimited list, + displays "data / color" using pre order strategy +Function input/parameters: pointer to current working node (RedBlackNodeType *), + pointer to row start flag + for first line of output (bool *) +Function output/parameters: none +Function output/returned: none +Device input/---: none +Device output/---: displayed as specified +Dependencies: printf, displayPreOrder (recursively) +*/ +void displayPreOrder(RedBlackNodeType *wkgPtr, bool *rowStartFlag) +{ + // check to see if the working pointer is null + if (wkgPtr != NULL) + { + // check to see if the rowStartFlag is true + if (rowStartFlag) + { + // if true, print the order + printf("Preorder : "); + // set the rowStartFlag to false + rowStartFlag = false; + } + // print out the string + printf(" %c/%c%s", wkgPtr->data, wkgPtr->color, SEMICOLON_BREAK); + // recurse to left node in tree + displayPreOrder(wkgPtr->leftChildPtr, rowStartFlag); + // recurse to right node in tree + displayPreOrder(wkgPtr->rightChildPtr, rowStartFlag); + } + // no return, void. +} + +/* +Name: displayTree +Process: controller function for calling appropriate tree traversal +Function input/parameters: pointer to current tree root (RedBlackNodeType *), + control codes INORDER_TRAVERSE, POSTORDER_TRAVERSE, + PREORDER_TRAVERSE +Function output/parameters: none +Function output/returned: none +Device input/---: none +Device output/---: displayed as specified +Dependencies: displayInOrder, displayPostOrder, displayPreOrder, printf +*/ +void displayTree(RedBlackNodeType *rootPtr, ControlCodes traverseCode) +{ + bool rowStarter = true; + // check to see which ControlCode was used, display based on this. + if(traverseCode == PREORDER_TRAVERSE) + { + printf("\n"); + // use the preorder traversal function + displayPreOrder(rootPtr, &rowStarter); + printf("\n"); + } + else if(traverseCode == INORDER_TRAVERSE) + { + printf("\n"); + // use the in order traversal function + displayInOrder(rootPtr, &rowStarter); + printf("\n"); + } + else + { + printf("\n"); + // use the postorder traversal function + displayPostOrder(rootPtr, &rowStarter); + printf("\n"); + } + // no return, void. +} + +/* +Name: findTreeHeight +Process: recursively finds height of tree +Function input/parameters: working pointer for recursion (RedBlackNodeType *) +Function output/parameters: none +Function output/returned: height of tree (int) +Device input/---: none +Device output/---: none +Dependencies: getMax +*/ +int findTreeHeight(RedBlackNodeType *localPtr) +{ + // check to see if at null + if(localPtr == NULL) + { + // return negative one since either empty or at bottom of tree + return -1; + } + else + { + // traverse the left and right subtrees + int leftTreeSize = findTreeHeight(localPtr->leftChildPtr); + int rightTreeSize = findTreeHeight(localPtr->rightChildPtr); + // return the max of the subtrees, add one for the local node + return getMax(leftTreeSize, rightTreeSize) + 1; + } +} + +/* +Name: initializeRBT +Process: returns NULL to tree root pointer to prepare tree for use +Function input/parameters: none +Function output/parameters: none +Function output/returned: NULL +Device input/---: none +Device output/---: none +Dependencies: none +*/ +RedBlackNodeType *initializeRBT() +{ + // return NULL to begin tree + return NULL; +} + +/* +Name: insert +Process: sets first node if tree is empty, otherwise calls helper + to set nodes, then calls RBT resolver to rebalance tree + if node is successfully inserted by helper, + prints inserting/resolving statement and root color set to black +Function input/parameters: tree root pointer (RedBlackNodeType *), + data to be inserted (char) +Function output/parameters: none +Function output/returned: pointer to updated tree root (RedBlackNodeType *) +Device input/---: none +Device output/---: none +Dependencies: printf, createNodeFromData, insertHelper, resolveRBT +*/ +RedBlackNodeType *insert(RedBlackNodeType *treeRoot, char inData) +{ + RedBlackNodeType *insertedNode; + // check if not null + if(treeRoot != NULL) + { + // use insertHelper to get to where the data needs to go + insertedNode = insertHelper(treeRoot, inData); + // print out what data is being added, tell user being resolved + printf("\nInserting %c and resolving\n", inData); + // use resolveRBT to get the tree balanced correctly + resolveRBT(&treeRoot, insertedNode); + } + else + { + // if inserting the root node + // set the root with createNodeFromData, node is black. + treeRoot = createNodeFromData(inData, BLACK); + // tell the user inserting the data + printf("\nInserting %c and resolving\n", inData); + // tell the user that the root was set, and is black. + printf(" - Root color set to black\n"); + /* AN ALTERNATIVE COULD BE TO INSTEAD + USE THE RESOLVE FUNCTION INSTEAD OF DOING IT BY HAND*/ + } + // return treeRoot + return treeRoot; +} + +/* +Name: insertHelper +Process: recursively finds place to add node, + places node using "look down" strategy, + returns newly inserted node pointer, + if duplicated nodes/keys attempted, returns NULL +Function input/parameters: working pointer for recursion (RedBlackNodeType *), + data to be inserted (char) +Function output/parameters: none +Function output/returned: pointer to inserted node (RedBlackNodeType *) +Device input/---: none +Device output/---: none +Dependencies: createNodeFromData, insertHelper (recursively) +*/ +RedBlackNodeType *insertHelper(RedBlackNodeType *wkgPtr, char inData) +{ + // compare between current node and inData + int diffChar = inData - wkgPtr->data; + + // check for moving left (diffChar < 0) + if(diffChar < 0) + { + // check for left child NULL + if(wkgPtr->leftChildPtr == NULL) + { + // assign current left child to a new node + wkgPtr->leftChildPtr = createNodeFromData(inData, RED); + // return pointer to the node added + return wkgPtr->leftChildPtr; + } + // return recursion + return insertHelper(wkgPtr->leftChildPtr, inData); + } + + // otherwise, check for moving right (diffChar > 0) + else if(diffChar > 0) + { + // check for right child NULL + if(wkgPtr->rightChildPtr == NULL) + { + // assign current right child to a new node + wkgPtr->rightChildPtr = createNodeFromData(inData, RED); + // return pointer to the node added + return wkgPtr->rightChildPtr; + } + // return recursion + return insertHelper(wkgPtr->rightChildPtr, inData); + } + + // otherwise, there is a duplicate + else + { + // return NULL + return NULL; + } +} + +/* +Name: isEmpty +Process: returns true if tree is empty, false otherwise +Function input/parameters: tree root pointer (RedBlackNodeType *) +Function output/parameters: none +Function output/returned: result of test (bool) +Device input/---: none +Device output/---: none +Dependencies: none +*/ +bool isEmpty(RedBlackNodeType *localPtr) +{ + // return test of root pointer is NULL + return localPtr == NULL; +} + +/* +Name: resolveRBT +Process: recursively checks tree for need to rebalance, + conducts rebalance as needed +Function input/parameters: address of tree root pointer (RedBlackNodeType **), + working pointer for recursion + which starts at the location + of the inserted node (RedBlackNodeType *) +Function output/parameters: none +Function output/returned: none +Device input/---: none +Device output/---: none +Dependencies: printf, rotateLeft, rotateRight, swapColors, + displayTreeStructure, displayDivider +*/ +void resolveRBT(RedBlackNodeType **treeRoot, RedBlackNodeType *wkgPtr) +{ + // declare parPtr, grndParPtr, unclePtr, grtGrndPtr + RedBlackNodeType *wkgParentPtr; + RedBlackNodeType *wkgGrandParentPtr; + RedBlackNodeType *wkgUnclePtr; + RedBlackNodeType *wkgGreatGrandParentPtr; + // check for parent and grandparent exists + if(wkgPtr->parentPtr != NULL && wkgPtr->parentPtr->parentPtr != NULL) + { + // set all my relatives, will need to know which child I am + wkgParentPtr = wkgPtr->parentPtr; + wkgGrandParentPtr = wkgParentPtr->parentPtr; + if (wkgParentPtr->leftChildPtr->data == wkgPtr->data) + { + // set the uncle pointer to the parent's right child + wkgUnclePtr = wkgParentPtr->rightChildPtr; + } + else + { + // set the uncle pointer to the parent's left child + wkgUnclePtr = wkgParentPtr->leftChildPtr; + } + wkgGreatGrandParentPtr = wkgGrandParentPtr->parentPtr; + // check for red uncle + if(wkgUnclePtr != NULL && wkgUnclePtr->color == RED) + { + // change parent and uncle to black + wkgParentPtr->color = BLACK; + wkgUnclePtr->color = BLACK; + // change grandparent to red + wkgGrandParentPtr->color = RED; + // recurse with the grandparent + resolveRBT(treeRoot, wkgGrandParentPtr); + } + // otherwise, assume uncle is black + else + { + // check for parent is left of grandparent + if(wkgGrandParentPtr->leftChildPtr->data == wkgParentPtr->data) + { + // check for child is left of parent (Left Left case) + if(wkgParentPtr->leftChildPtr->data == wkgPtr->data) + { + printf("\nLL Case, rotate right\n"); + // use rotate right with grandparent(old) and parent(new) + // link the parent to grandparent's parent + // swap colors called with parent and grandparent + } + // check for child is right of parent (Left Right case) + if(wkgParentPtr->rightChildPtr->data == wkgPtr->data) + { + printf("\nLR Case, rotate right, recurse\n"); + // use rotate right with parent(old) and createdNode(new) + // call resolveRBT with parent as createdNode (will treat as LLC) + } + } + // check for parent is right of grandparent + if(wkgGrandParentPtr->rightChildPtr->data == wkgParentPtr->data) + { + // check for child is right of parent (Right Right case) + if(wkgParentPtr->rightChildPtr->data == wkgPtr->data) + { + printf("\nRR Case, rotate left\n"); + // use rotate left with grandparent(old) and parent(new) + // link the parent to grandparent's parent + // swap colors called with parent and grandparent + } + // check for child is left of parent (Right Left case) + if(wkgParentPtr->leftChildPtr->data == wkgPtr->data) + { + printf("\nRL Case, rotate left, recurse\n"); + // use rotate left with parent(old) and createdNode(new) + // call resolveRBT with parent as createdNode (will treat as RRC) + } + } + } + // end of par/gpr test + } + // check for current node is root pointer + if(wkgPtr == *treeRoot) + { + // paint it black + wkgPtr->color = BLACK; + } + // no return, void. +} + +/* +Name: rotateLeft +Process: "rotates" nodes to the left by resetting pointers + to related nodes +Function input/parameters: old and new top node pointers (RedBlackNodeType *) +Function output/parameters: none +Function output/returned: pointer to new top node (RedBlackNodeType *) +Device input/---: none +Device output/---: none +Dependencies: none +*/ +RedBlackNodeType *rotateLeft(RedBlackNodeType *newTopPtr, + RedBlackNodeType *oldTopPtr) +{ + // set the old top's parent's right child to the new top + oldTopPtr->parentPtr->rightChildPtr = newTopPtr; + // set the old top's right child to the new top's left child + oldTopPtr->rightChildPtr = newTopPtr->leftChildPtr; + // set the new top's parent to old top's parent + newTopPtr->parentPtr = oldTopPtr->parentPtr; + // set the new top's left child to old top + newTopPtr->leftChildPtr = oldTopPtr; + // set the old top's parent to new top + oldTopPtr->parentPtr = newTopPtr; + // return new top + return newTopPtr; +} + +/* +Name: rotateRight +Process: "rotates" nodes to the right by resetting pointers + to related nodes +Function input/parameters: old and new top node pointers (RedBlackNodeType *) +Function output/parameters: none +Function output/returned: pointer to new top node (RedBlackNodeType *) +Device input/---: none +Device output/---: none +Dependencies: none +*/ +RedBlackNodeType *rotateRight(RedBlackNodeType *newTopPtr, + RedBlackNodeType *oldTopPtr) +{ + // set the old top's parent's left child to the new top + oldTopPtr->parentPtr->leftChildPtr = newTopPtr; + // set the old top's left child to the new top's right child + oldTopPtr->leftChildPtr = newTopPtr->rightChildPtr; + // set the new top's parent to old top's parent + newTopPtr->parentPtr = oldTopPtr->parentPtr; + // set the new top's right child to old top + newTopPtr->rightChildPtr = oldTopPtr; + // set the old top's parent to new top + oldTopPtr->parentPtr = newTopPtr; + // return new top + return newTopPtr; +} + +/* +Name: swapColors +Process: swaps or exchanges colors between two nodes +Function input/parameters: pointers to two nodes (RedBlackNodeType *) +Function output/parameters: none +Function output/returned: updated pointers to two nodes (RedBlackNodeType *) +Device input/---: none +Device output/---: none +Dependencies: none +*/ +void swapColors(RedBlackNodeType *one, RedBlackNodeType *other) +{ + // define temporary holding place for one color + int tempColor = one->color; + // swap the colors using the temp. + one->color = other->color; + other->color = tempColor; + // no return, void. +} //////////////////////////////////////////////////////////////////////////////// // No student coding below this point