diff --git a/PA09-1108/GeneralUtility.c b/PA09-1108/GeneralUtility.c new file mode 100644 index 0000000..2b30327 --- /dev/null +++ b/PA09-1108/GeneralUtility.c @@ -0,0 +1,206 @@ +// header file +#include "GeneralUtility.h" + +// constants + +/* Data Structures + +typedef enum { NO_RESULT = -1, INITIALIZE_RAND_GENERATOR = 101, + GET_RANDOM_VALUE, CLEAR_RAND_GENERATOR } RandControlCode; + +typedef enum { LOW_RAND_LIMIT = 10, HIGH_RAND_LIMIT = 99 } RandLimits; + +Data Structures */ + +// function implementations + +/* +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 string character for character up to NULL_CHAR of source string +Function input/parameters: source string to be copied (const char *) +Function output/parameters: destination string (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: privateGenUniqueRandom +Process: generates a unique random value for a given set of data + during a program, + for control code: + INITIALIZE_RAND_GENERATOR - initializes lookup array for use + GET_RANDOM_VALUE - creates, tests, and returns random value + CLEAR_RAND_GENERATOR - deallocates lookup array +Method input/parameters: HeapType item (const HeapType), + control code (RandControlCode) +Method output/parameters: none +Method output/returned: unique random value (int) +Device input/---: none +Device output/---: none +Dependencies: srand, privateGetRandBetween, privateIsInArray, malloc, free +Notes: protects from: + accidental reinitialization, + acquiring value without initialization, + or deallocation without initialization +*/ +int privateGenUniqueRandom(int heapCapacity, RandControlCode ctrlCode) +{ + // define the static array and size + static int *randArray = NULL; + static int size = 0; + // check which ctrlCode is used + if(ctrlCode == INITIALIZE_RAND_GENERATOR) + { + // if initializing + // create the array with the capacity given + randArray = (int *)malloc(sizeof(int) * heapCapacity); + // set random seed + srand(time(NULL)); + // set size to zero(just to be safe) + size = 0; + } + else if(ctrlCode == GET_RANDOM_VALUE) + { + // if requesting for rand + // generate random value, + // makes sure the value currently isn't in the array + int currentRand = privateGetRandBetween(LOW_RAND_LIMIT, HIGH_RAND_LIMIT); + while (privateIsInArray(randArray, size, currentRand)) + { + // generate new random. + currentRand = privateGetRandBetween(LOW_RAND_LIMIT, HIGH_RAND_LIMIT); + } + // once found a number that isn't in array, put into array. + randArray[size] = currentRand; + // increment size + size = size + 1; + return currentRand; + } + // check to see if the array is actually initialized + if(size != 0 && randArray != NULL) + { + // otherwise, clearing and freeing things if initialized. + free(randArray); + } + return NO_RESULT; +} + +/* +Name: privateGetRandBetween +Process: generates a random value between two limits, inclusive +Method input/parameters: lower and upper limits (int) +Method output/parameters: none +Method output/returned: random value generated as specified (int) +Device input/---: none +Device output/---: none +Dependencies: rand +*/ +int privateGetRandBetween(int lowLimit, int highLimit) +{ + // return random number that was previously seeded + return ((rand() % (highLimit - lowLimit + 1)) + lowLimit); +} + +/* +Name: privateGetStringLen +Process: finds length of string +Function input/parameters: c-style 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: privateIsInArray +Process: provided integer array, its size, and a test value, + returns true if test value is in the array, false otherwise +Method input/parameters: integer array (int *), + test value (int) +Method output/parameters: none +Method output/returned: Boolean result of operation (bool) +Device input/---: none +Device output/---: none +Dependencies: none +*/ +bool privateIsInArray(const int *array, int size, int testVal) +{ + int arrayIterator; + // for loop through the array. + for(arrayIterator = 0; arrayIterator < size; arrayIterator++) + { + // check to see if the testVal is at the location. + if(array[arrayIterator] == testVal) + { + // if there, return true + return true; + } + } + // otherwise, return false since not found + return false; +} \ No newline at end of file diff --git a/PA09-1108/HeapUtility.c b/PA09-1108/HeapUtility.c new file mode 100644 index 0000000..8db54ad --- /dev/null +++ b/PA09-1108/HeapUtility.c @@ -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. +} \ No newline at end of file diff --git a/PA09-1108/PA09_Main b/PA09-1108/PA09_Main new file mode 100755 index 0000000..adac5ce Binary files /dev/null and b/PA09-1108/PA09_Main differ diff --git a/PA09-1108/StudentUtility.c b/PA09-1108/StudentUtility.c new file mode 100644 index 0000000..3a6d0d7 --- /dev/null +++ b/PA09-1108/StudentUtility.c @@ -0,0 +1,67 @@ +// header file +#include "StudentUtility.h" + +// constants + +/* Data Structures + +typedef struct StudentStruct + { + char name[ MAX_STR_LEN ]; + int studentId; + char gender; + double gpa; + int priority; + + } StudentType; + +typedef struct StudentArrayStruct + { + StudentType *array; + + int size, capacity; + } StudentArrayType; + +Data Structures */ + +// function implementations + +/* +Name: deepCopyStudentDAta +Process: copies one StudentType item into another +Function input/parameters: source data (const StudentType) +Function output/parameters: destination data (StudentType *) +Function output/returned: none +Device input/ ---: none +Device output/ ---: none +Dependencies: privateCopyString +*/ +void deepCopyStudentData(StudentType *dest, const StudentType source) +{ + // copy each piece of data out of the source given + privateCopyString(dest->name, source.name); + dest->studentId = source.studentId; + dest->gender = source.gender; + dest->gpa = source.gpa; + dest->priority = source.priority; + // no return, void. +} + +/* +Name: studentDataToString +Process: creates display string from all object data +Method input/parameters: none +Method output/parameters: pointer to return string (char * const) +Method output/returned: none +Device input/keyboard: none +Device output/monitor: none +Dependencies: sprintf +*/ +void studentDataToString(char *outString, const StudentType toDisplay) +{ + // use sprintf to "cast" the data to a string + sprintf(outString, "Nm: %s, Id: %d, Gndr: %c, GPA: %.4f, Priority: %d\n", + toDisplay.name, toDisplay.studentId, toDisplay.gender, + toDisplay.gpa, toDisplay.priority); + // no return, void. +} \ No newline at end of file