CS249-Projects/PA07-1025/BST_Utility.c
cdez a3ec33a917 Mostly Completed PA07
+- BST_Utility.c
+- PA07_Main
2023-10-25 16:48:10 -07:00

659 lines
No EOL
22 KiB
C

// header files
#include "BST_Utility.h"
/* Data Structures
typedef struct stateDataStruct
{
char state[ MIN_STR_LEN ];
double avgTemp;
double lowestTemp;
double highestTemp;
struct stateDataStruct *leftChildPtr;
struct stateDataStruct *rightChildPtr;
} StateDataType;
Data Structures */
// function implementations
/*
Name: clearTree
Process: recursively returns dynamically allocated data to the OS
Function input/parameters: working pointer for recursion (StudentDataType *)
Function output/parameters: none
Function output/returned: empty tree (NULL)
Device input/ ---: none
Device output/ ---: none
Dependencies: free, clearTree (recursively)
*/
StateDataType *clearTree( StateDataType *wkgPtr )
{
// recurse through the left children
if(wkgPtr->leftChildPtr != NULL)
{
clearTree(wkgPtr->leftChildPtr);
}
// recurse through the right children
if(wkgPtr->rightChildPtr != NULL)
{
clearTree(wkgPtr->rightChildPtr);
}
// otherwise, free the working pointer if at end of getting to bottom tree
free(wkgPtr);
// return NULL since no tree left
return NULL;
}
/*
Name: privateCompareStrings
Process: compares two strings as follows:
- if left string is alphabetically greater than the right string,
returns value greater than zero
- if left string is alphabetically less than the right string,
returns value less than zero
- if strings are alphabetically equal but one is longer,
longer one is greater
- otherwise, returns zero
Function input/parameters: two strings to be compared (const char *)
Function output/parameters: none
Function output/returned: result as specified above (int)
Device input/ ---: none
Device output/ ---: none
Dependencies: privateGetStringLen
*/
int privateCompareStrings( const char *leftStr, const char *rightStr )
{
int diff, index = 0;
int leftStrLen = privateGetStringLen(leftStr);
int rightStrLen = privateGetStringLen(rightStr);
while(index < leftStrLen && index < rightStrLen)
{
diff = leftStr[index] - rightStr[index];
if(diff != 0)
{
return diff;
}
index = index + 1;
}
return leftStrLen - rightStrLen;
}
/*
Name: privateCopyString
Process: copies one string into another,
assumes destination string has appropriate capacity
Function input/parameters: source string (const char *)
Function output/parameters: destination string (const char *)
Function output/returned: none
Device input/ ---: none
Device output/ ---: none
Dependencies: none
*/
void privateCopyString( char *dest, const char *source )
{
int characterCount = 0;
// use a while loop, check for !NULL_CHAR
while(source[characterCount] != NULL_CHAR)
{
// copy the character accessed into dest string
dest[characterCount] = source[characterCount];
// iterate the number of characters
characterCount = characterCount + 1;
}
// add a NULL_CHAR once done, characterCount is in the right place for \0
dest[characterCount] = NULL_CHAR;
// no return, void
}
/*
Name: copyTree
Process: recursively duplicates the provided tree
using a pre order traversal strategy
Function input/parameters: working pointer for recursion (StateDataType *)
Function output/parameters: none
Function output/returned: pointer to duplicate tree (StateDataType *)
Device input/ ---: none
Device output/ ---: none
Dependencies: initializeStateNodeFromNode, copyTree (recursively)
*/
StateDataType *copyTree( StateDataType *wkgPtr )
{
// make a storage pointer
StateDataType *copyPtr = NULL;
// check for not equal to null
if(wkgPtr != NULL)
{
// create the pointer given data
copyPtr = initializeStateNodeFromNode(*wkgPtr);
// recurse left child
copyPtr->leftChildPtr = copyTree(wkgPtr->leftChildPtr);
// recurse right child
copyPtr->rightChildPtr = copyTree(wkgPtr->rightChildPtr);
}
// return copyPtr
return copyPtr;
}
/*
Name: displayInOrder
Process: recursively displays tree using in order traversal
Function input/parameters: working pointer for recursion (StateDataType *)
Function output/parameters: none
Function output/returned: none
Device input/ ---: none
Device output/ ---: none
Dependencies: stateDataToString, printf
*/
void displayInOrder( StateDataType *sdtPtr, int *itemNum )
{
// create empty string
char displayString[STD_STR_LEN];
if(sdtPtr != NULL)
{
// recurse to left node in tree
displayInOrder(sdtPtr->leftChildPtr, itemNum);
// increment the item
*itemNum = *itemNum + 1;
// setup the string
stateDataToString(*sdtPtr, displayString);
// print out the string
printf("%2d) %s", *itemNum, displayString);
// recurse to right node in tree
displayInOrder(sdtPtr->rightChildPtr, itemNum);
}
// no return, void
}
/*
Name: displayPostOrder
Process: recursively displays tree using post order traversal
Function input/parameters: working pointer for recursion (StateDataType *)
Function output/parameters: none
Function output/returned: none
Device input/ ---: none
Device output/ ---: none
Dependencies: stateDataToString, printf
*/
void displayPostOrder( StateDataType *sdtPtr, int *itemNum )
{
// create empty string
char displayString[STD_STR_LEN];
if(sdtPtr != NULL)
{
// recurse to left node in tree
displayPostOrder(sdtPtr->leftChildPtr, itemNum);
// recurse to right node in tree
displayPostOrder(sdtPtr->rightChildPtr, itemNum);
// increment the item
*itemNum = *itemNum + 1;
// setup the string
stateDataToString(*sdtPtr, displayString);
// print out the string
printf("%2d) %s", *itemNum, displayString);
}
// no return, void
}
/*
Name: displayPreOrder
Process: recursively displays tree using pre order traversal
Function input/parameters: working pointer for recursion (StateDataType *)
Function output/parameters: none
Function output/returned: none
Device input/ ---: none
Device output/ ---: none
Dependencies: stateDataToString, printf
*/
void displayPreOrder( StateDataType *sdtPtr, int *itemNum )
{
// create empty string
char displayString[STD_STR_LEN];
if(sdtPtr != NULL)
{
// increment the item
*itemNum = *itemNum + 1;
// setup the string
stateDataToString(*sdtPtr, displayString);
// print out the string
printf("%2d) %s", *itemNum, displayString);
// recurse to left node in tree
displayPostOrder(sdtPtr->leftChildPtr, itemNum);
// recurse to right node in tree
displayPostOrder(sdtPtr->rightChildPtr, itemNum);
}
// no return, void
}
/*
Name: privateGetStringLen
Process: finds length of string
Function input/parameters: string (const char *)
Function output/parameters: none
Function output/returned: calculated length of string (int)
Device input/ ---: none
Device output/ ---: none
Dependencies: none
*/
int privateGetStringLen( const char *str )
{
int strLen = 0;
// while through string until hit null.
while(str[strLen] != NULL_CHAR)
{
// increment the length string iterator
strLen = strLen + 1;
}
// return strLen
return strLen;
}
/*
Name: initializeBST
Process: sets BST root pointer to NULL, root pointer is returned by address
Function input/parameters: address of working pointer (StateDataType **)
Function output/parameters: address of updated working pointer
(StateDataType **)
Function output/returned: none
Device input/ ---: none
Device output/ ---: none
Dependencies: none
*/
void initializeBST( StateDataType **bstPtr )
{
// initialize the address of the BST to null
*bstPtr = NULL;
// no return, void
}
/*
Name: initializeStateNodeFromData
Process: captures data from individual data items,
dynamically creates new node,
copies data, and returns pointer to new node
Function input/parameters: data to be copied
name (const char *)
temperatures (double)
Function output/parameters: none
Function output/returned: pointer to new node as specified (StateDataType *)
Device input/ ---: none
Device output/ ---: none
Dependencies: malloc, sizeof, privateCopyString
*/
StateDataType *initializeStateNodeFromData( const char *state, double avgTemp,
double lowTemp, double highTemp )
{
// declare node
StateDataType *initNode;
// create the node using malloc
initNode = malloc(sizeof(StateDataType));
// copy the state into the node
privateCopyString(initNode->state, state);
// copy the avgTemp, lowTemp, and highTemp into node
initNode->avgTemp = avgTemp;
initNode->lowestTemp = lowTemp;
initNode->highestTemp = highTemp;
// return the node
return initNode;
}
/*
Name: initializeStateNodeFromNode
Process: captures data from source node pointer, dynamically creates new node,
copies data, and returns pointer to new node
Function input/parameters: node to be copied (StateDataType)
Function output/parameters: none
Function output/returned: pointer to new node as specified (StateDataType *)
Device input/ ---: none
Device output/ ---: none
Dependencies: initializeStateNodeFromData
Notes: one line of code
*/
StateDataType *initializeStateNodeFromNode( const StateDataType source )
{
// return the initializeStateNodeFromData function with correct data
return initializeStateNodeFromData(source.state, source.avgTemp,
source.lowestTemp, source.highestTemp);
}
/*
Name: insert
Process: recursively searches for available node in BST,
creates new node and returns it to the calling function,
if node is already in tree, data is overwritten
Function input/parameters: working pointer for recursion (StateDataType *),
node to be inserted (const StateDataType)
Function output/parameters: none
Function output/returned: pointer to new node as specified (StateDataType *)
Device input/ ---: none
Device output/ ---: none
Dependencies: privateCompareStrings,
setStateNodeData, initializeStateNodeFromNode
Notes: No redundant code permitted
*/
StateDataType *insert( StateDataType *wkgPtr, const StateDataType inData )
{
// define space for node
StateDataType *insertNode;
int stringComparator;
// check to see if the working pointer is not null
if(wkgPtr != NULL)
{
// set string comparator
stringComparator = privateCompareStrings(inData.state, wkgPtr->state);
// compare the value less than
if(stringComparator < 0)
{
// workingPtr -> nextPtr = insert(workingPtr->nextPtr, data);
wkgPtr->leftChildPtr = insert(wkgPtr->leftChildPtr, inData);
}
// compare the value greater than
if(stringComparator > 0)
{
// workingPtr -> nextPtr = insert(workingPtr->nextPtr, data);
wkgPtr->rightChildPtr = insert(wkgPtr->rightChildPtr, inData);
}
// compare the value equal to
if(stringComparator == 0)
{
// replaces the data (using setStateNodeData?)
setStateNodeData(wkgPtr, inData);
}
}
// otherwise, create node
else
{
// create the node using function
insertNode = initializeStateNodeFromNode(inData);
// return created node
return insertNode;
}
// return working pointer to prev recursion
return wkgPtr;
}
/*
Name: isEmpty
Process: tests root node for NULL, returns result
Function input/parameters: pointer to root node (StateDataType *)
Function output/parameters: none
Function output/returned: result of test as specified (bool)
Device input/ ---: none
Device output/ ---: none
Dependencies: none
*/
bool isEmpty( StateDataType *sdtPtr)
{
// return check for rootNode being NULL
return sdtPtr == NULL;
}
/*
Name: removeFromMin
Process: recursively searches for min node,
when found, node is unlinked from tree, and returned
Function input/parameters: pointers to parent and child nodes (StateDataType *)
Function output/parameters: none
Function output/returned: pointer to removed node (StateDataType *)
Device input/ ---: none
Device output/ ---: none
Dependencies: removeFromMin (recursively)
*/
StateDataType *removeFromMin( StateDataType *parentPtr,
StateDataType *childPtr )
{
// check to see if the left child pointer is null
if(childPtr->leftChildPtr != NULL)
{
// keep going left until end
childPtr->leftChildPtr = removeFromMin(childPtr, childPtr->leftChildPtr);
}
else
{
// once found, delink between the parent and child
parentPtr->leftChildPtr = childPtr->rightChildPtr;
}
// return removed ptr
return childPtr;
}
/*
Name: removeItem
Process: searches for item, if found, creates new node from search pointer,
then removes item from tree using helper function,
otherwise returns NULL
Function input/parameters: address of pointer to root node (StateDataType *),
node to be removed with at least state name key
(const StateDataType)
Function output/parameters: address of updated root node pointer
(StateDataType **)
Function output/returned: pointer to removed item node (StateDataType *)
Device input/ ---: none
Device output/ ---: none
Dependencies: search, initializeStateNodeFromNode, removeItemHelper
*/
bool removeItem( StateDataType **rootPtr,
StateDataType *removedData, const StateDataType outData )
{
StateDataType *searchPtr;
// check to see if the BST is there
if(rootPtr != NULL)
{
// search for the data in the tree
searchPtr = search(*rootPtr, outData);
// check to see if data was found from search to remove
if(searchPtr != NULL)
{
// if found, set the search value to removedData
*removedData = *searchPtr;
// start the recursions down to the remove value
*rootPtr = removeItemHelper(*rootPtr, outData);
// return success with item removal
return true;
}
}
// set removeData to NULL since no value found
removedData = NULL;
// return false since no item found or tree empty/not found
return false;
}
/*
Name: removeItemHelper
Process: recursively searches for item, removes node,
returns dynamic memory of removed node to OS,
returns updated link to parent (at each recursive level),
only one return at end of function
Function input/parameters: pointer to working node (StateDataType *),
node to be removed with at least state name key
(const StateDataType)
Function output/parameters: none
Function output/returned: link to recursive parent
Device input/ ---: none
Device output/ ---: none
Dependencies: privateCompareStrings, setStateDataNode, removeFromMin,
free, removeItemHelper (recursively)
Notes: No redundant code permitted
*/
StateDataType *removeItemHelper( StateDataType *wkgPtr,
const StateDataType outData )
{
// create, initialize result of compare strings
int stringComparator;
stringComparator = privateCompareStrings(outData.state, wkgPtr->state);
StateDataType *removalPtr;
// check for moving to left
if(stringComparator < 0)
{
// - recurse to left, link to left child
wkgPtr->leftChildPtr = removeItemHelper(wkgPtr->leftChildPtr, outData);
}
// otherwise, check for moving to right
else if(stringComparator > 0)
{
// - recurse to right, link to right child
wkgPtr->rightChildPtr = removeItemHelper(wkgPtr->rightChildPtr, outData);
}
// otherwise, check for left child null
else if(wkgPtr->leftChildPtr == NULL)
{
// - set a temp pointer to the wkg pointer
removalPtr = wkgPtr;
// - set return pointer to its right child
wkgPtr = wkgPtr->rightChildPtr;
// - free temp pointer
free(removalPtr);
}
// otherwise, check for right child null
else if(wkgPtr->rightChildPtr == NULL)
{
// - set a temp pointer to the wkg pointer
removalPtr = wkgPtr;
// - set return pointer to its left child
wkgPtr = wkgPtr->rightChildPtr;
// - free temp pointer
free(removalPtr);
}
// otherwise, check for right child has no left child
else if(wkgPtr->rightChildPtr->leftChildPtr == NULL)
{
// - copy the data from the right child into the current node
setStateNodeData(wkgPtr, *wkgPtr->rightChildPtr);
// - set a temp pointer to the right child
removalPtr = wkgPtr->rightChildPtr;
// - link around the right child
wkgPtr->rightChildPtr = removalPtr->rightChildPtr;
// - free the right child node
free(removalPtr);
}
// otherwise // , assume right child has left child
else
{
// - call removeFromMin, capture the returned node,
removalPtr = removeFromMin(wkgPtr, wkgPtr->rightChildPtr);
// - set the current node from the captured node
setStateNodeData(wkgPtr, *removalPtr);
// - free the captured node (temp ptr)
free(removalPtr);
}
// recommend one return at the bottom of function, will give back wkgPtr
return wkgPtr;
}
/*
Name: search
Process: recursively searches for item, if found, returns pointer to node,
otherwise, returns NULL
Function input/parameters: pointer to working node (StateDataType *),
node to be found with at least state name key
(const StateDataType)
Function output/parameters: none
Function output/returned: link to found node, or NULL, as specified
Device input/ ---: none
Device output/ ---: none
Dependencies: compareStrings
Notes: No redundant code permitted
*/
StateDataType *search( StateDataType *wkgPtr, const StateDataType searchData )
{
// define the string comparison number
int stringComparator = privateCompareStrings(searchData.state,
wkgPtr->state);
// check to see if at the end of tree
if(wkgPtr != NULL)
{
// check the left side of the tree
if(stringComparator < 0)
{
return search(wkgPtr->leftChildPtr, searchData);
}
// check the right side of the tree
else if(stringComparator > 0)
{
return search(wkgPtr->rightChildPtr, searchData);
}
// otherwise, data has been found
else
{
// return the found value
return wkgPtr;
}
}
// otherwise, return null for not found
return NULL;
}
/*
Name: setStateNodeToEmpty
Process: sets state node to empty or default values
Function input/parameters: pointer to node (StateDataType *)
Function output/parameters: pointer to updated node (StateDataType *)
Function output/returned: none
Device input/ ---: none
Device output/ ---: none
Dependencies: none
*/
void setStateNodeToEmpty( StateDataType *node )
{
// set the state to null character
node->state[0] = '\0';
// set the average temp to 0
node->avgTemp = 0;
// set the lowest temp to 0
node->lowestTemp = 0;
// set the highest temp to 0
node->highestTemp = 0;
// (not sure if messing with pointers)
node->leftChildPtr = NULL;
node->rightChildPtr = NULL;
// no return, void
}
/*
Name: setStateNodeData
Process: copies data from source node to destination pointer
Function input/parameters: node to be copied (StateDataType)
Function output/parameters: destination pointer (StateDataType *)
Function output/returned: none
Device input/ ---: none
Device output/ ---: none
Dependencies: copyString
*/
void setStateNodeData( StateDataType *destPtr, const StateDataType source )
{
// copy the state from source to dest with privateCopyString
privateCopyString(destPtr->state, source.state);
// copy the average temp from source to dest
destPtr->avgTemp = source.avgTemp;
// copy the lowest temp from source to dest
destPtr->lowestTemp = source.lowestTemp;
// copy the highest temp from source to dest
destPtr->highestTemp = source.highestTemp;
// (not sure if messing with pointers)
// destPtr->leftChildPtr = source.leftChildPtr;
// destPtr->rightChildPtr = source.rightChildPtr;
// no return, void
}
/*
Name: stateDataToString
Process: sets data from node to formatted string
Function input/parameters: node with data to be set (StateDataType)
Function output/parameters: string array with result (char [])
Function output/returned: none
Device input/ ---: none
Device output/ ---: none
Dependencies: sprintf
*/
void stateDataToString( StateDataType stateData, char str[] )
{
// use sprintf to load the state name into str
// use sprintf to load the average temp into str
// use sprintf to load the lowest temp into str
// use sprintf to load the highest temp into str
// this is done all at once to avoid many lines
sprintf(str, "%s/%0.2f/%0.2f/%0.2f\n", stateData.state, stateData.avgTemp,
stateData.lowestTemp, stateData.highestTemp);
// no return, void
}