A lightweight game engine for the MBED.

Dependencies:   mbed 4DGL-uLCD-SE MMA8452

Committer:
Yehowshua
Date:
Sat Mar 16 05:26:30 2019 +0000
Revision:
5:f86f447a295f
Parent:
2:5645cb2d9316
now with inputs

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Yehowshua Immanuel 2:5645cb2d9316 1 /****************************************************************************
Yehowshua Immanuel 2:5645cb2d9316 2 * Include the Public Interface
Yehowshua Immanuel 2:5645cb2d9316 3 *
Yehowshua Immanuel 2:5645cb2d9316 4 * By including the public interface at the top of the file, the compiler can
Yehowshua Immanuel 2:5645cb2d9316 5 * enforce that the function declarations in the the header are not in
Yehowshua Immanuel 2:5645cb2d9316 6 * conflict with the definitions in the file. This is not a guarantee of
Yehowshua Immanuel 2:5645cb2d9316 7 * correctness, but it is better than nothing!
Yehowshua Immanuel 2:5645cb2d9316 8 ***************************************************************************/
Yehowshua Immanuel 2:5645cb2d9316 9 #include "hash_table.h"
Yehowshua Immanuel 2:5645cb2d9316 10
Yehowshua Immanuel 2:5645cb2d9316 11
Yehowshua Immanuel 2:5645cb2d9316 12 /****************************************************************************
Yehowshua Immanuel 2:5645cb2d9316 13 * Include other private dependencies
Yehowshua Immanuel 2:5645cb2d9316 14 *
Yehowshua Immanuel 2:5645cb2d9316 15 * These other modules are used in the implementation of the hash table module,
Yehowshua Immanuel 2:5645cb2d9316 16 * but are not required by users of the hash table.
Yehowshua Immanuel 2:5645cb2d9316 17 ***************************************************************************/
Yehowshua Immanuel 2:5645cb2d9316 18 #include <stdlib.h> // For malloc and free
Yehowshua Immanuel 2:5645cb2d9316 19 #include <stdio.h> // For printf
Yehowshua Immanuel 2:5645cb2d9316 20
Yehowshua Immanuel 2:5645cb2d9316 21
Yehowshua Immanuel 2:5645cb2d9316 22 /****************************************************************************
Yehowshua Immanuel 2:5645cb2d9316 23 * Hidden Definitions
Yehowshua Immanuel 2:5645cb2d9316 24 *
Yehowshua Immanuel 2:5645cb2d9316 25 * These definitions are not available outside of this file. However, because
Yehowshua Immanuel 2:5645cb2d9316 26 * the are forward declared in hash_table.h, the type names are
Yehowshua Immanuel 2:5645cb2d9316 27 * available everywhere and user code can hold pointers to these structs.
Yehowshua Immanuel 2:5645cb2d9316 28 ***************************************************************************/
Yehowshua Immanuel 2:5645cb2d9316 29 /**
Yehowshua Immanuel 2:5645cb2d9316 30 * This structure represents an a hash table.
Yehowshua Immanuel 2:5645cb2d9316 31 */
Yehowshua Immanuel 2:5645cb2d9316 32 struct _HashTable {
Yehowshua Immanuel 2:5645cb2d9316 33 /** The array of pointers to the head of a singly linked list, whose nodes
Yehowshua Immanuel 2:5645cb2d9316 34 are HashTableEntry objects */
Yehowshua Immanuel 2:5645cb2d9316 35 HashTableEntry** buckets;
Yehowshua Immanuel 2:5645cb2d9316 36
Yehowshua Immanuel 2:5645cb2d9316 37 /** The hash function pointer */
Yehowshua Immanuel 2:5645cb2d9316 38 HashFunction hash;
Yehowshua Immanuel 2:5645cb2d9316 39
Yehowshua Immanuel 2:5645cb2d9316 40 /** The number of buckets in the hash table */
Yehowshua Immanuel 2:5645cb2d9316 41 unsigned int num_buckets;
Yehowshua Immanuel 2:5645cb2d9316 42 };
Yehowshua Immanuel 2:5645cb2d9316 43
Yehowshua Immanuel 2:5645cb2d9316 44 /**
Yehowshua Immanuel 2:5645cb2d9316 45 * This structure represents a hash table entry.
Yehowshua Immanuel 2:5645cb2d9316 46 */
Yehowshua Immanuel 2:5645cb2d9316 47 struct _HashTableEntry {
Yehowshua Immanuel 2:5645cb2d9316 48 /** The key for the hash table entry */
Yehowshua Immanuel 2:5645cb2d9316 49 unsigned int key;
Yehowshua Immanuel 2:5645cb2d9316 50
Yehowshua Immanuel 2:5645cb2d9316 51 /** The value associated with this hash table entry */
Yehowshua Immanuel 2:5645cb2d9316 52 void* value;
Yehowshua Immanuel 2:5645cb2d9316 53
Yehowshua Immanuel 2:5645cb2d9316 54 /**
Yehowshua Immanuel 2:5645cb2d9316 55 * A pointer pointing to the next hash table entry
Yehowshua Immanuel 2:5645cb2d9316 56 * NULL means there is no next entry (i.e. this is the tail)
Yehowshua Immanuel 2:5645cb2d9316 57 */
Yehowshua Immanuel 2:5645cb2d9316 58 HashTableEntry* next;
Yehowshua Immanuel 2:5645cb2d9316 59 };
Yehowshua Immanuel 2:5645cb2d9316 60
Yehowshua Immanuel 2:5645cb2d9316 61
Yehowshua Immanuel 2:5645cb2d9316 62 /****************************************************************************
Yehowshua Immanuel 2:5645cb2d9316 63 * Private Functions
Yehowshua Immanuel 2:5645cb2d9316 64 *
Yehowshua Immanuel 2:5645cb2d9316 65 * These functions are not available outside of this file, since they are not
Yehowshua Immanuel 2:5645cb2d9316 66 * declared in hash_table.h.
Yehowshua Immanuel 2:5645cb2d9316 67 ***************************************************************************/
Yehowshua Immanuel 2:5645cb2d9316 68 /**
Yehowshua Immanuel 2:5645cb2d9316 69 * createHashTableEntry
Yehowshua Immanuel 2:5645cb2d9316 70 *
Yehowshua Immanuel 2:5645cb2d9316 71 * Helper function that creates a hash table entry by allocating memory for it on
Yehowshua Immanuel 2:5645cb2d9316 72 * the heap. It initializes the entry with key and value, initialize pointer to
Yehowshua Immanuel 2:5645cb2d9316 73 * the next entry as NULL, and return the pointer to this hash table entry.
Yehowshua Immanuel 2:5645cb2d9316 74 *
Yehowshua Immanuel 2:5645cb2d9316 75 * @param key The key corresponds to the hash table entry
Yehowshua Immanuel 2:5645cb2d9316 76 * @param value The value stored in the hash table entry
Yehowshua Immanuel 2:5645cb2d9316 77 * @return The pointer to the hash table entry
Yehowshua Immanuel 2:5645cb2d9316 78 */
Yehowshua Immanuel 2:5645cb2d9316 79 static HashTableEntry* createHashTableEntry(unsigned int key, void* value) {
Yehowshua Immanuel 2:5645cb2d9316 80 // Create an initialize a new hash table entry.
Yehowshua Immanuel 2:5645cb2d9316 81 HashTableEntry* newEntry = (HashTableEntry*)malloc(sizeof(HashTableEntry));
Yehowshua Immanuel 2:5645cb2d9316 82 newEntry->key = key;
Yehowshua Immanuel 2:5645cb2d9316 83 newEntry->value = value;
Yehowshua Immanuel 2:5645cb2d9316 84 newEntry->next = NULL;
Yehowshua Immanuel 2:5645cb2d9316 85
Yehowshua Immanuel 2:5645cb2d9316 86 return newEntry;
Yehowshua Immanuel 2:5645cb2d9316 87 }
Yehowshua Immanuel 2:5645cb2d9316 88
Yehowshua Immanuel 2:5645cb2d9316 89 /**
Yehowshua Immanuel 2:5645cb2d9316 90 * findItem
Yehowshua Immanuel 2:5645cb2d9316 91 *
Yehowshua Immanuel 2:5645cb2d9316 92 * Helper function that checks whether there exists the hash table entry that
Yehowshua Immanuel 2:5645cb2d9316 93 * contains a specific key.
Yehowshua Immanuel 2:5645cb2d9316 94 *
Yehowshua Immanuel 2:5645cb2d9316 95 * @param myHashTable The pointer to the hash table.
Yehowshua Immanuel 2:5645cb2d9316 96 * @param key The key corresponds to the hash table entry
Yehowshua Immanuel 2:5645cb2d9316 97 * @return The pointer to the hash table entry, or NULL if key does not exist
Yehowshua Immanuel 2:5645cb2d9316 98 */
Yehowshua Immanuel 2:5645cb2d9316 99 static HashTableEntry* findItem(HashTable* myHashTable, unsigned int key) {
Yehowshua Immanuel 2:5645cb2d9316 100 unsigned int bucketNum = myHashTable->hash(key); // Get the bucket number.
Yehowshua Immanuel 2:5645cb2d9316 101 HashTableEntry* temp = myHashTable->buckets[bucketNum]; // Get the head entry.
Yehowshua Immanuel 2:5645cb2d9316 102
Yehowshua Immanuel 2:5645cb2d9316 103 if (temp == NULL) return NULL; // If there's nothing in the bucket, return NULL.
Yehowshua Immanuel 2:5645cb2d9316 104
Yehowshua Immanuel 2:5645cb2d9316 105 while (temp!=NULL) {
Yehowshua Immanuel 2:5645cb2d9316 106 if (temp->key==key) return temp; // Return the hash table entry if the key is found.
Yehowshua Immanuel 2:5645cb2d9316 107 temp = temp->next; // Otherwise, move to next node.
Yehowshua Immanuel 2:5645cb2d9316 108 }
Yehowshua Immanuel 2:5645cb2d9316 109
Yehowshua Immanuel 2:5645cb2d9316 110 return NULL; // Return NULL if key is not present.
Yehowshua Immanuel 2:5645cb2d9316 111 }
Yehowshua Immanuel 2:5645cb2d9316 112
Yehowshua Immanuel 2:5645cb2d9316 113 /****************************************************************************
Yehowshua Immanuel 2:5645cb2d9316 114 * Public Interface Functions
Yehowshua Immanuel 2:5645cb2d9316 115 *
Yehowshua Immanuel 2:5645cb2d9316 116 * These functions implement the public interface as specified in the header
Yehowshua Immanuel 2:5645cb2d9316 117 * file, and make use of the private functions and hidden definitions in the
Yehowshua Immanuel 2:5645cb2d9316 118 * above sections.
Yehowshua Immanuel 2:5645cb2d9316 119 ****************************************************************************/
Yehowshua Immanuel 2:5645cb2d9316 120 HashTable* createHashTable(HashFunction myHashFunc, unsigned int numBuckets) {
Yehowshua Immanuel 2:5645cb2d9316 121 // The hash table has to contain at least one bucket. Exit gracefully if
Yehowshua Immanuel 2:5645cb2d9316 122 // this condition is not met.
Yehowshua Immanuel 2:5645cb2d9316 123 if (numBuckets==0) {
Yehowshua Immanuel 2:5645cb2d9316 124 printf("Hash table has to contain at least 1 bucket...\n");
Yehowshua Immanuel 2:5645cb2d9316 125 exit(1);
Yehowshua Immanuel 2:5645cb2d9316 126 }
Yehowshua Immanuel 2:5645cb2d9316 127
Yehowshua Immanuel 2:5645cb2d9316 128 // Allocate memory for the new HashTable struct on heap.
Yehowshua Immanuel 2:5645cb2d9316 129 HashTable* newTable = (HashTable*)malloc(sizeof(HashTable));
Yehowshua Immanuel 2:5645cb2d9316 130
Yehowshua Immanuel 2:5645cb2d9316 131 // Initialize the components of the new HashTable struct.
Yehowshua Immanuel 2:5645cb2d9316 132 newTable->hash = myHashFunc;
Yehowshua Immanuel 2:5645cb2d9316 133 newTable->num_buckets = numBuckets;
Yehowshua Immanuel 2:5645cb2d9316 134 newTable->buckets = (HashTableEntry**)malloc(numBuckets*sizeof(HashTableEntry*));
Yehowshua Immanuel 2:5645cb2d9316 135
Yehowshua Immanuel 2:5645cb2d9316 136 // As the new buckets contain indeterminant values, init each bucket as NULL.
Yehowshua Immanuel 2:5645cb2d9316 137 unsigned int i;
Yehowshua Immanuel 2:5645cb2d9316 138 for (i=0; i<numBuckets; ++i) {
Yehowshua Immanuel 2:5645cb2d9316 139 newTable->buckets[i] = NULL;
Yehowshua Immanuel 2:5645cb2d9316 140 }
Yehowshua Immanuel 2:5645cb2d9316 141
Yehowshua Immanuel 2:5645cb2d9316 142 // Return the newly created hash table.
Yehowshua Immanuel 2:5645cb2d9316 143 return newTable;
Yehowshua Immanuel 2:5645cb2d9316 144 }
Yehowshua Immanuel 2:5645cb2d9316 145
Yehowshua Immanuel 2:5645cb2d9316 146 void destroyHashTable(HashTable* myHashTable) {
Yehowshua Immanuel 2:5645cb2d9316 147 unsigned int i;
Yehowshua Immanuel 2:5645cb2d9316 148 HashTableEntry* temp;
Yehowshua Immanuel 2:5645cb2d9316 149 HashTableEntry* next;
Yehowshua Immanuel 2:5645cb2d9316 150
Yehowshua Immanuel 2:5645cb2d9316 151 // Loop through each bucket of the hash table to remove all items.
Yehowshua Immanuel 2:5645cb2d9316 152 for (i=0; i<myHashTable->num_buckets; ++i) {
Yehowshua Immanuel 2:5645cb2d9316 153 temp = myHashTable->buckets[i]; // set temp to be the first entry of the ith bucket
Yehowshua Immanuel 2:5645cb2d9316 154
Yehowshua Immanuel 2:5645cb2d9316 155 // delete all entries
Yehowshua Immanuel 2:5645cb2d9316 156 while (temp != NULL) {
Yehowshua Immanuel 2:5645cb2d9316 157 next = temp->next;
Yehowshua Immanuel 2:5645cb2d9316 158 free(temp->value);
Yehowshua Immanuel 2:5645cb2d9316 159 free(temp);
Yehowshua Immanuel 2:5645cb2d9316 160 temp = next;
Yehowshua Immanuel 2:5645cb2d9316 161 }
Yehowshua Immanuel 2:5645cb2d9316 162 }
Yehowshua Immanuel 2:5645cb2d9316 163
Yehowshua Immanuel 2:5645cb2d9316 164 // free buckets
Yehowshua Immanuel 2:5645cb2d9316 165 free(myHashTable->buckets);
Yehowshua Immanuel 2:5645cb2d9316 166
Yehowshua Immanuel 2:5645cb2d9316 167 // free hash table
Yehowshua Immanuel 2:5645cb2d9316 168 free(myHashTable);
Yehowshua Immanuel 2:5645cb2d9316 169 }
Yehowshua Immanuel 2:5645cb2d9316 170
Yehowshua Immanuel 2:5645cb2d9316 171 void* insertItem(HashTable* myHashTable, unsigned int key, void* value) {
Yehowshua Immanuel 2:5645cb2d9316 172 // First, we want to check if the key is present in the hash table.
Yehowshua Immanuel 2:5645cb2d9316 173 HashTableEntry* temp = findItem(myHashTable, key);
Yehowshua Immanuel 2:5645cb2d9316 174
Yehowshua Immanuel 2:5645cb2d9316 175 if (temp) {
Yehowshua Immanuel 2:5645cb2d9316 176 // The key is present in the hash table.
Yehowshua Immanuel 2:5645cb2d9316 177 void* oldValue = temp->value;
Yehowshua Immanuel 2:5645cb2d9316 178 temp->value = value;
Yehowshua Immanuel 2:5645cb2d9316 179 return oldValue;
Yehowshua Immanuel 2:5645cb2d9316 180 } else {
Yehowshua Immanuel 2:5645cb2d9316 181 // The key is not present in the hash table.
Yehowshua Immanuel 2:5645cb2d9316 182 temp = createHashTableEntry(key, value);
Yehowshua Immanuel 2:5645cb2d9316 183 temp->next = myHashTable->buckets[myHashTable->hash(key)];
Yehowshua Immanuel 2:5645cb2d9316 184 myHashTable->buckets[myHashTable->hash(key)] = temp;
Yehowshua Immanuel 2:5645cb2d9316 185 return NULL; // Return NULL as nothing is overwritten.
Yehowshua Immanuel 2:5645cb2d9316 186 }
Yehowshua Immanuel 2:5645cb2d9316 187 }
Yehowshua Immanuel 2:5645cb2d9316 188
Yehowshua Immanuel 2:5645cb2d9316 189 void* getItem(HashTable* myHashTable, unsigned int key) {
Yehowshua Immanuel 2:5645cb2d9316 190 // First, we want to check if the key is present in the hash table.
Yehowshua Immanuel 2:5645cb2d9316 191 HashTableEntry* temp = findItem(myHashTable, key);
Yehowshua Immanuel 2:5645cb2d9316 192
Yehowshua Immanuel 2:5645cb2d9316 193 if (temp) // if the key exists
Yehowshua Immanuel 2:5645cb2d9316 194 return temp->value;
Yehowshua Immanuel 2:5645cb2d9316 195 else // return NULL if the key does not exist
Yehowshua Immanuel 2:5645cb2d9316 196 return NULL;
Yehowshua Immanuel 2:5645cb2d9316 197 }
Yehowshua Immanuel 2:5645cb2d9316 198
Yehowshua Immanuel 2:5645cb2d9316 199 void* removeItem(HashTable* myHashTable, unsigned int key) {
Yehowshua Immanuel 2:5645cb2d9316 200 // Reference: https://www.geeksforgeeks.org/linked-list-set-3-deleting-node/
Yehowshua Immanuel 2:5645cb2d9316 201 unsigned int bucketNum = myHashTable->hash(key); // get the bucket number
Yehowshua Immanuel 2:5645cb2d9316 202 HashTableEntry* temp = myHashTable->buckets[bucketNum]; // get the head entry
Yehowshua Immanuel 2:5645cb2d9316 203 HashTableEntry* prev;
Yehowshua Immanuel 2:5645cb2d9316 204
Yehowshua Immanuel 2:5645cb2d9316 205 // If head holds the key
Yehowshua Immanuel 2:5645cb2d9316 206 if (temp != NULL && temp->key == key) {
Yehowshua Immanuel 2:5645cb2d9316 207 myHashTable->buckets[bucketNum] = temp->next; // Change head
Yehowshua Immanuel 2:5645cb2d9316 208 void* oldValue = temp->value; // hold the old value
Yehowshua Immanuel 2:5645cb2d9316 209 free(temp);
Yehowshua Immanuel 2:5645cb2d9316 210 return oldValue;
Yehowshua Immanuel 2:5645cb2d9316 211 }
Yehowshua Immanuel 2:5645cb2d9316 212
Yehowshua Immanuel 2:5645cb2d9316 213 // Search for the key to be removed
Yehowshua Immanuel 2:5645cb2d9316 214 while (temp != NULL && temp->key != key) {
Yehowshua Immanuel 2:5645cb2d9316 215 prev = temp;
Yehowshua Immanuel 2:5645cb2d9316 216 temp = temp->next;
Yehowshua Immanuel 2:5645cb2d9316 217 }
Yehowshua Immanuel 2:5645cb2d9316 218
Yehowshua Immanuel 2:5645cb2d9316 219 // If the key is not present in the list
Yehowshua Immanuel 2:5645cb2d9316 220 if (temp == NULL) return NULL;
Yehowshua Immanuel 2:5645cb2d9316 221
Yehowshua Immanuel 2:5645cb2d9316 222 // Unlink the node from list
Yehowshua Immanuel 2:5645cb2d9316 223 prev->next = temp->next;
Yehowshua Immanuel 2:5645cb2d9316 224 void* oldValue = temp->value; // hold the old value
Yehowshua Immanuel 2:5645cb2d9316 225 free(temp);
Yehowshua Immanuel 2:5645cb2d9316 226
Yehowshua Immanuel 2:5645cb2d9316 227 return oldValue;
Yehowshua Immanuel 2:5645cb2d9316 228 }
Yehowshua Immanuel 2:5645cb2d9316 229
Yehowshua Immanuel 2:5645cb2d9316 230 void deleteItem(HashTable* myHashTable, unsigned int key) {
Yehowshua Immanuel 2:5645cb2d9316 231 // remove the entry and free the returned data
Yehowshua Immanuel 2:5645cb2d9316 232 free(removeItem(myHashTable, key));
Yehowshua Immanuel 2:5645cb2d9316 233 }