From a62aa61957636663317ddc49c61847a5055c40e6 Mon Sep 17 00:00:00 2001 From: cdez Date: Wed, 15 Nov 2023 15:12:03 -0700 Subject: [PATCH] COMPLETED PA10 and CS249! +- HashUtility.c --- PA10-1115/HashUtility.c | 218 +++++++++++++++++++++++++++++++++++----- 1 file changed, 191 insertions(+), 27 deletions(-) diff --git a/PA10-1115/HashUtility.c b/PA10-1115/HashUtility.c index 73df61d..b87fdb4 100644 --- a/PA10-1115/HashUtility.c +++ b/PA10-1115/HashUtility.c @@ -4,6 +4,10 @@ #include "StateDataUtility.h" // constants +const int MINIMUM_HASH_LETTER_COUNT = 7; +const int ITEM_NOT_FOUND = -1; +const bool USED_NODE = true; +const bool UNUSED_NODE = false; /* Data Structures typedef struct HashStruct @@ -34,8 +38,13 @@ Dependencies: setDataNodeFromData, addItemFromStruct bool addItemFromData( ProbingHashType *hashTable, const char *stateName, double avgTemp, double lowTemp, double highTemp ) { - // return false (temp) - return false; + StateDataType createState; + // sets a node from the data using the function + setDataNodeFromData(&createState, stateName, avgTemp, + lowTemp, highTemp, UNUSED_NODE); + // uses add item from struct to add the data and do the calling. + // return addItemFromStruct + return addItemFromStruct(hashTable, createState); } /* @@ -55,8 +64,58 @@ Dependencies: getHashIndex, privateToPower, printf, stateDataToString, */ bool addItemFromStruct( ProbingHashType *hashTable, StateDataType newItem ) { - // return false (temp) - return false; + // initialize function/variables + char stateString[MAX_STR_LEN]; + // create offset variable + int hashOffset = 0; + // get hash value, assign to hashIndex variable + int hashIndex = getHashIndex(*hashTable, newItem); + // set a temp node with index + StateDataType currentNode; + int workingIndex = hashIndex; + setDataNodeFromStruct(¤tNode, newItem); + // loop until location found + // iterate no more than HT size AND element is in use + printf("\nIndices Probed: %d", workingIndex); + while(workingIndex <= hashTable->tableSize && + hashTable->array[workingIndex].inUse) + { + // increment the offset variable + hashOffset = hashOffset + 1; + // check for linear probe type + if(hashTable->probeStrategy == LINEAR_PROBING) + { + // set working variable to the hash index plus the offset + workingIndex = hashIndex + hashOffset; + printf(", %d", workingIndex % hashTable->tableSize); + } + // otherwise, assume quadratic probe type + else + { + // set working variable to the hash index plus the offset squared + workingIndex = hashIndex + privateToPower(hashOffset, 2); + printf(", %d", workingIndex % hashTable->tableSize); + } + // mod by table size to keep index in bounds + workingIndex = workingIndex % hashTable->tableSize; + // set temp node to the new index + } + printf("\n"); + stateDataToString(stateString, currentNode); + printf("%s, %d -> %d\n", stateString, hashIndex, workingIndex); + // end index loop + // check for failed correct index + if(hashOffset == hashTable->tableSize) + { + // return false + return false; + } + // complete the data - set the temp value's inUse to true + currentNode.inUse = USED_NODE; + // assign to array (use setDataNodeFromStruct) + setDataNodeFromStruct(&hashTable->array[workingIndex], currentNode); + // return true + return true; } /* @@ -128,8 +187,19 @@ Dependencies: findItemIndex, setEmptyDataNode StateDataType findItem( const ProbingHashType *hashTable, StateDataType searchItem ) { - // return NULL (temp) - return; + int indexFound; + StateDataType foundItem; + // set the return item to empty as default + setEmptyDataNode(&foundItem); + // use findItemIndex to search for the item + indexFound = findItemIndex(hashTable, searchItem); + if (indexFound != ITEM_NOT_FOUND) + { + // return the hashTable at index data. + return hashTable->array[indexFound]; + } + // return foundItem with blank data + return foundItem; } /* @@ -149,8 +219,60 @@ Dependencies: getHashIndex, printf, privateCompareStrings, privateToPower, */ int findItemIndex( const ProbingHashType *hashTable, StateDataType searchItem ) { - // return zero (temp) - return 0; + // initialize function/variables + int findIterator; + // set hash index to getHashIndex + int hashIndex = getHashIndex(*hashTable, searchItem); + // declare added value, set to zero + int addedVal = 0; + // declare working index + int workingIndex = hashIndex; + // set the value into a temp + // test the value, set compare to int var + int strCompare = privateCompareStrings(hashTable->array[workingIndex].name, + searchItem.name); + // print indices probed, with hash index + printf("\nIndices Probed: %d", workingIndex); + // loop up to table size with added value AND value not found + // value not found => test for equality of name + for(findIterator = 0; findIterator < hashTable->tableSize && strCompare != 0; + findIterator++) + { + // increment the added value + addedVal = addedVal + 1; + // check for linear probing type + if(hashTable->probeStrategy == LINEAR_PROBING) + { + // get a working index from the hash index plus the added value + workingIndex = hashIndex + addedVal; + } + // otherwise, assume quadratic + else + { + // get a working index from the hash index + // plus the added value squared + workingIndex = hashIndex + privateToPower(addedVal, 2); + } + // process the working index to set it within array indices + workingIndex = workingIndex % hashTable->tableSize; + // print index probed, with comma delimiter + printf(", %d", workingIndex); + // set the value into a temp + // test the value, set compare to int var + strCompare = privateCompareStrings(hashTable->array[workingIndex].name, + searchItem.name); + } + // end of loop + // print an endline + printf("\n"); + // check for item not found (added value is up at hash table size) + if(addedVal == hashTable->tableSize) + { + // return item not found + return ITEM_NOT_FOUND; + } + // return working index + return workingIndex; } /* @@ -169,8 +291,33 @@ Dependencies: privateGetStringLength */ int getHashIndex( const ProbingHashType hashTable, const StateDataType state ) { - // return zero (temp) - return 0; + int hashIndex = 0, hashDiff = 0, hashIterator; + // check to see if the state name length is less than MIN HASH LETTER COUNT + // if it is, take a difference of the minimum letter count, then loop + if(privateGetStringLength(state.name) < MINIMUM_HASH_LETTER_COUNT) + { + // set the hash difference + hashDiff = MINIMUM_HASH_LETTER_COUNT - privateGetStringLength(state.name); + } + // otherwise, for loop through the name of the state + for(hashIterator = 0; hashIterator < privateGetStringLength(state.name); + hashIterator++) + { + // loop through the state's characters, add them up. + hashIndex = hashIndex + (int)state.name[hashIterator]; + } + // if the state does not meet the minimum, then loop through the difference. + for(hashIterator = 0; hashIterator < hashDiff; hashIterator++) + { + // since the requirement wasn't met, and if the difference is greater than + // zero, then this loop will fill in the gap. + hashIndex = hashIndex + (int)state.name[hashIterator]; + } + // since the hash index is now a number, must mod by table size in order to + // get an index value that is range fitted. + hashIndex = hashIndex % hashTable.tableSize; + // return hashIndex + return hashIndex; } /* @@ -226,7 +373,21 @@ Dependencies: findItemIndex, setDataNodeFromStruct bool removeState( StateDataType *removedState, const StateDataType toBeRemoved, const ProbingHashType hashTable ) { - // return false (temp) + int removeIndex; + // get the index of the item + removeIndex = findItemIndex(&hashTable, toBeRemoved); + // check to see if the item was not found + // if the item was found, then 'remove' it by setting to unused. + if(removeIndex != ITEM_NOT_FOUND) + { + // set the removed state to where the item is in array + setDataNodeFromStruct(removedState, hashTable.array[removeIndex]); + // set the state to unused in the array to let overwriting possible + hashTable.array[removeIndex].inUse = UNUSED_NODE; + // return true since operation success + return true; + } + // return false since item not found return false; } @@ -247,41 +408,44 @@ Dependencies: sprintf, printf */ void showHashTableStatus( const ProbingHashType hashTable) { - int itemCount = 0, statusIterator, contigCount, maxContig, minContig; + int itemCount = 0, statusIterator, maxContig = 0, minContig = 0; + int unusedCount = 0; // display the hash table status, then iterate through either used/unused printf("\nHash Table Status: "); - for(statusIterator = 0; statusIterator < hashTable.tableSize; statusIterator++) + for(statusIterator = 0; statusIterator < hashTable.tableSize; + statusIterator++) { - contigCount = 1; // check to see if inUse if(hashTable.array[statusIterator].inUse) { // print 'D' printf("D"); + // increment the item count actual itemCount = itemCount + 1; - contigCount = contigCount + 1; - // check to see if the contigCount is bigger than old maxContig - if (contigCount > maxContig) + // increment the minimum number of contiguous elements + minContig = minContig + 1; + // check to see if the min exceeds max + if(minContig > maxContig) { - maxContig = contigCount; + // assign the max to min since it exceeded + maxContig = minContig; } } else { - // check to see if the contigCount is less than old minContig - if(contigCount < minContig) - { - minContig = contigCount; - } - contigCount = 1; + // reset the minimum value to zero. + minContig = 0; // print 'U' printf("U"); + // keep count of the actual unused values. + unusedCount = unusedCount + 1; } } + // print out the table of important values. printf("\nD => Data, U => Unused\n\n"); printf(" Items in Hash Table: %d\n", itemCount); - printf(" Minimum contiguous bins: %d\n", itemCount); - printf(" Maximum contiguous bins: %d\n", itemCount); - printf(" Number of empty bins: %d\n", itemCount); + printf(" Minimum contiguous bins: %d\n", minContig); + printf(" Maximum contiguous bins: %d\n", maxContig); + printf(" Number of empty bins: %d\n", unusedCount); // no return, void. } \ No newline at end of file