"Finish" PA09

+- GeneralUtility.c
+- HeapUtility.c
+- StudentUtility.c
+- PA09_Main
This commit is contained in:
Charles Descamps 2023-11-08 17:15:25 -07:00
parent 146e26b5cf
commit d9e90f6501
4 changed files with 663 additions and 0 deletions

390
PA09-1108/HeapUtility.c Normal file
View file

@ -0,0 +1,390 @@
// header file
#include "HeapUtility.h"
// constants
/* Data Structures
typedef struct HeapStruct
{
StudentType *array;
int size, capacity;
} HeapType;
Data Structures */
// function implementations
/*
Name: addStudentWithData
Process: adds student data to the array with internally generated priority,
returns true if array not full, false otherwise
Method input/parameters: pointer to HeapType item (HeapType *),
name (const char *), student id (int),
gender (char), gpa (double), priority (int),
display flag (bool)
Method output/parameters: pointer to HeapType item (HeapType *)
Method output/returned: Boolean result of function (bool)
Device input/---: none
Device output/---: none
Dependencies: privateCopyString, privateGenUniqueRandom,
studentDataToString, privateBubbleUp
*/
bool addStudentWithData(HeapType *heap, const char *inName, int inStudentId,
char inGender, double inGpa, bool displayFlag)
{
// create variables for string display
char dispString[MAX_STR_LEN];
// check to see if the size is equal to capacity
if(heap->size == heap->capacity)
{
// if the capacity and the size are equal
return false;
}
// copy the data out of the input variables
privateCopyString(heap->array[heap->size].name, inName);
heap->array[heap->size].studentId = inStudentId;
heap->array[heap->size].gender = inGender;
heap->array[heap->size].gpa = inGpa;
heap->array[heap->size].priority =
privateGenUniqueRandom(heap->capacity, GET_RANDOM_VALUE);
// display if enabled
if(displayFlag)
{
// "cast" our data to a string
studentDataToString(dispString, heap->array[heap->size]);
// print out the string
printf("\nAdding new student: %s\n", dispString);
}
// call bubble up to get to the right place
privateBubbleUp(heap, heap->size, displayFlag);
// increment the size of the heap
heap->size = heap->size + 1;
// return true since operation complete
return true;
}
/*
Name: addStudentFromStudentElement
Process: adds student element to the array from other element,
returns true if array not full, false otherwise
Method input/parameters: student data type item to be added (const StudentType)
Method output/parameters: pointer to HeapType (HeapType *)
Method output/returned: Boolean result of function
Device input/---: none
Device output/---: none
Dependencies: one line of code - addStudentWithData
*/
bool addStudentFromElement(HeapType *heap,
const StudentType sourceElement, bool displayFlag)
{
// return the added student with data
return addStudentWithData(heap, sourceElement.name, sourceElement.studentId,
sourceElement.gender, sourceElement.gpa, displayFlag);
}
/*
Name: clearHeapType
Process: deallocates heap and internal array, clears unique random source,
returns NULL
Method input/parameters: pointer to HeapType (HeapType *)
Method output/parameters: none
Method output/returned: NULL (HeapType *)
Device input/---: none
Device output/---: none
Dependencies: free, privateGenUniqueRandom
*/
HeapType *clearHeapType(HeapType *heap)
{
// free the heap's array
free(heap->array);
// free the random number generator
privateGenUniqueRandom(heap->capacity, CLEAR_RAND_GENERATOR);
// free the rest of the heap
free(heap);
// return NULL since cleared
return NULL;
}
/*
Name: createHeapType
Process: initializes heap, and internal array, creates unique random source
Method input/parameters: capacity (int)
Method output/parameters: none
Method output/returned: initialized heap (HeapType *)
Device input/---: none
Device output/---: none
Dependencies: malloc, privateGenUniqueRandom
*/
HeapType *createHeapType(int capacity)
{
// dynamically allocate the heap
HeapType *createdHeap = (HeapType *) malloc(sizeof(HeapType));
// set the heap's capacity to the given capacity
createdHeap->capacity = capacity;
// set the heap's size to zero to start
createdHeap->size = 0;
// allocate the internal array for the heap
createdHeap->array = (StudentType *) malloc(sizeof(StudentType) * capacity);
// initialize the random number generator
privateGenUniqueRandom(capacity, INITIALIZE_RAND_GENERATOR);
// return created heap
return createdHeap;
}
/*
Name: getTreeHeight
Process: recursively finds tree height by using number of nodes
Method input/parameters: node count (int)
Method output/parameters: none
Method output/returned: calculated tree height (int)
Device input/---: none
Device output/---: none
Dependencies: findTreeHeight (recursively)
*/
int findTreeHeight(int nodeCount)
{
// define height
int treeHeight = 0;
// check to see if the count of nodes is more than zero
if(nodeCount > 1)
{
// count the tree height recursively.
treeHeight = 1 + findTreeHeight((nodeCount - 1)/2);
}
// return treeHeight
return treeHeight;
}
/*
Name: isEmpty
Process: checks for empty list, reports
Method input/parameters: none
Method output/parameters: none
Method output/returned: Boolean result of operation (bool)
Device input/---: none
Device output/---: none
Dependencies: none
*/
bool isEmpty(HeapType *heap)
{
// return false (temp)
return heap->size == 0;
}
/*
Name: privateBubbleUp
Process: recursively traverses tree to place new data element
in the correct location in the tree/array,
if display flag set, reports bubble up actions
Method input/parameters: pointer to heap (HeapType *),
index at current location in tree/array (int),
display flag (bool)
Method output/parameters: pointer to updated heap (HeapType *)
Method output/returned: none
Device input/---: none
Device output/---: none
Dependencies: deepCopyStudentData, printf, studentDataToString,
privateBubbleUp (recursive)
Notes: No more than two statements for any swap operation
*/
void privateBubbleUp(HeapType *heap, int currentIndex, bool displayFlag)
{
// initialize variables
int parentIndex = (currentIndex - 1) / 2;
char bubbleStr[MAX_STR_LEN];
StudentType swapParent;
// prepare the swap
deepCopyStudentData(&swapParent, heap->array[currentIndex]);
// check for parent and valid index
if(parentIndex >= 0) //used to be currentIndex > 0
{
// compare parent and child priorities
if(heap->array[parentIndex].priority <
heap->array[currentIndex].priority)
{
// if priorities are BLANK than, swap.
deepCopyStudentData(&heap->array[currentIndex],
heap->array[parentIndex]);
deepCopyStudentData(&heap->array[parentIndex], swapParent);
// check for display information
if(displayFlag)
{
// "cast" data to string
studentDataToString(bubbleStr, heap->array[parentIndex]);
// print the bubbling
printf(" - Bubble up swap:\n");
// print the swapping parts
printf(" - moving up child: %s", bubbleStr);
studentDataToString(bubbleStr, heap->array[currentIndex]);
printf(" - moving down parent: %s\n", bubbleStr);
}
// bubbleUp again since swapped
privateBubbleUp(heap, parentIndex, displayFlag);
}
}
// no return, void.
}
/*
Name: privateTrickleDown
Process: recursively traverses tree to place reordered data element
in the correct location in the tree/array,
if display flag set, reports trickle down actions
Method input/parameters: pointer to heap (HeapType *),
index at current location in tree/array (int),
display flag (bool)
Method output/parameters: pointer to updated heap (HeapType *)
Method output/returned: none
Device input/---: none
Device output/---: none
Dependencies: deepCopyStudentData, printf, studentDataToString,
privateTrickleDown (recursive)
Notes: No more than two copy operations for any swap operation
*/
void privateTrickleDown(HeapType *heap, int currentIndex, bool displayFlag)
{
// initialize variables
bool leftChildSwap = false, rightChildSwap = false;
int leftChildIndex = currentIndex * 2 + 1;
int rightChildIndex = currentIndex * 2 + 2;
int swapStudentIndex;
StudentType swapStudent;
char trickleStr[MAX_STR_LEN];
// check left child and data(priority)
if(heap->size <= leftChildIndex)
{
// check left child exists (given index within size)
// compare currentIndex priority < leftChildPriority
if(heap->array[leftChildIndex].priority >
heap->array[currentIndex].priority)
{
// left child > currentIndex, leftChildSwap = true
leftChildSwap = true;
}
}
// otherwise, check right child and data(priority)
else
{
// check right child exists (given index within size)
// compare currentIndex priority < rightChildPriority
if (heap->array[rightChildIndex].priority >
heap->array[currentIndex].priority)
{
// right child > currentIndex, rightChildSwap = true
rightChildSwap = true;
}
}
// decide to swap with left or right child based on which is max priority
// if both can be swapped, take the greater priority one.
if(leftChildSwap && rightChildSwap)
{
// set the swapStudent to the greater priority (deepCopy)
// set the swapStudentIndex to whichever side was picked
if(heap->array[leftChildIndex].priority >
heap->array[rightChildIndex].priority)
{
rightChildSwap = false;
}
else
{
leftChildSwap = false;
}
}
// check to see if the leftChildSwap is true
else if(leftChildSwap)
{
// set the swapStudent to the leftChild
deepCopyStudentData(&swapStudent, heap->array[leftChildIndex]);
// set the swapStudentIndex to the left
swapStudentIndex = leftChildIndex;
}
// otherwise, check to see if the rightChildSwap is true
else if(rightChildSwap)
{
// set the swapStudent to the rightChild
deepCopyStudentData(&swapStudent, heap->array[rightChildIndex]);
// set the swapStudentIndex to the right
swapStudentIndex = rightChildIndex;
}
// swapping operation block and check
if(leftChildSwap || rightChildSwap)
{
// check if displayFlag is true
if (displayFlag)
{
// print out the relevant information
printf(" - Trickle down swap:\n");
studentDataToString(trickleStr, heap->array[currentIndex]);
printf(" - moving down parent:%s", trickleStr);
// get the swapping side index information
studentDataToString(trickleStr, heap->array[swapStudentIndex]);
// check which side is being swapped to display accurate info
if(leftChildSwap)
{
printf(" - moving up left child:%s\n", trickleStr);
}
else
{
printf(" - moving up right child:%s\n", trickleStr);
}
}
// swapping operation given that there needs to be a swap
// heap->array[swapStudentIndex] = heap->array[currentIndex]
deepCopyStudentData(&heap->array[swapStudentIndex],
heap->array[currentIndex]);
// heap->array[currentIndex] = swapStudent
deepCopyStudentData(&heap->array[currentIndex], swapStudent);
// trickleDown to next recursion since swapped
privateTrickleDown(heap, swapStudentIndex, displayFlag);
}
// no return, void.
}
/*
Name: removeItem
Process: removes item from heap, adjusts tree, returns
Method input/parameters: pointer to heap type (HeapType *)
Method output/parameters: returned data, or empty returnVal if not found
(StudentDataType *),
pointer to updated heap type (HeapType *)
Method output/returned: none
Device input/---: none
Device output/---: none
Dependencies: deepCopyStudentData, studentDataToString,
printf, privateTrickleDown
*/
void removeItem(StudentType *returnVal, HeapType *heap, bool displayFlag)
{
// define a removedItemStr
char removedItemStr[MAX_STR_LEN];
// removes item @ index zero
// (item @ last index of array @ index zero)
// check to make sure within valid space
if(heap->size > 0)
{
// set the returnVal to the heap's index zero by deep copy
deepCopyStudentData(returnVal, heap->array[0]);
// set last to first
deepCopyStudentData(&heap->array[0], heap->array[heap->size - 1]);
// decrement size by 1 for array
heap->size = heap->size - 1;
// check the displayFlag
if (displayFlag)
{
studentDataToString(removedItemStr, *returnVal);
// if true, print the removed item
// print the string for the removed item
printf("\nRemoving student: %s\n", removedItemStr);
}
// call privateTrickleDown to move into correct place
privateTrickleDown(heap, 0, displayFlag);
if (displayFlag)
{
// show the removed student complete
printf("%s removed\n", removedItemStr);
}
}
// no return, void.
}