Unfortunate Stopping Point

+- RedBlackTreeUtility.c
++ PA08_Main
This commit is contained in:
Charles Descamps 2023-10-29 15:07:29 -07:00
parent 37f0a97939
commit c2068d6874
2 changed files with 608 additions and 1 deletions

BIN
PA08-1101/PA08_Main Executable file

Binary file not shown.

View file

@ -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