180 lines
4.7 KiB
C
180 lines
4.7 KiB
C
/*
|
|
* Tabulka s rozptýlenými položkami
|
|
*
|
|
* S využitím datových typů ze souboru hashtable.h a připravených koster
|
|
* funkcí implementujte tabulku s rozptýlenými položkami s explicitně
|
|
* zretězenými synonymy.
|
|
*
|
|
* Při implementaci uvažujte velikost tabulky HT_SIZE.
|
|
*/
|
|
|
|
#include "hashtable.h"
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
int HT_SIZE = MAX_HT_SIZE;
|
|
|
|
/*
|
|
* Rozptylovací funkce která přidělí zadanému klíči index z intervalu
|
|
* <0,HT_SIZE-1>. Ideální rozptylovací funkce by měla rozprostírat klíče
|
|
* rovnoměrně po všech indexech. Zamyslete sa nad kvalitou zvolené funkce.
|
|
*/
|
|
int get_hash(char *key) {
|
|
int result = 1;
|
|
int length = strlen(key);
|
|
for (int i = 0; i < length; i++) {
|
|
result += key[i];
|
|
}
|
|
return (result % HT_SIZE);
|
|
}
|
|
|
|
/*
|
|
* Inicializace tabulky — zavolá sa před prvním použitím tabulky.
|
|
*/
|
|
void ht_init(ht_table_t *table) {
|
|
// Inicializujeme všetky položky na NULL
|
|
for (int i = 0; i < HT_SIZE; i++) {
|
|
(*table)[i] = NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Vyhledání prvku v tabulce.
|
|
*
|
|
* V případě úspěchu vrací ukazatel na nalezený prvek; v opačném případě vrací
|
|
* hodnotu NULL.
|
|
*/
|
|
ht_item_t *ht_search(ht_table_t *table, char *key) {
|
|
// Získame index pomocou hash funkcie
|
|
int index = get_hash(key);
|
|
|
|
// Prechádzame zoznam synoným
|
|
ht_item_t *item = (*table)[index];
|
|
while (item != NULL) {
|
|
// Ak nájdeme kľúč, vrátime položku
|
|
if (strcmp(item->key, key) == 0) {
|
|
return item;
|
|
}
|
|
item = item->next;
|
|
}
|
|
|
|
// Prvok nebol nájdený
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* Vložení nového prvku do tabulky.
|
|
*
|
|
* Pokud prvek s daným klíčem už v tabulce existuje, nahraďte jeho hodnotu.
|
|
*
|
|
* Při implementaci využijte funkci ht_search. Pri vkládání prvku do seznamu
|
|
* synonym zvolte nejefektivnější možnost a vložte prvek na začátek seznamu.
|
|
*/
|
|
void ht_insert(ht_table_t *table, char *key, float value) {
|
|
// Skúsime nájsť existujúci prvok
|
|
ht_item_t *item = ht_search(table, key);
|
|
|
|
if (item != NULL) {
|
|
// Ak existuje, aktualizujeme hodnotu
|
|
item->value = value;
|
|
} else {
|
|
// Vytvoríme nový prvok
|
|
int index = get_hash(key);
|
|
item = malloc(sizeof(ht_item_t));
|
|
if (item == NULL) {
|
|
return; // Chyba alokácie
|
|
}
|
|
|
|
// Alokujeme a skopírujeme kľúč
|
|
item->key = malloc(strlen(key) + 1);
|
|
if (item->key == NULL) {
|
|
free(item);
|
|
return;
|
|
}
|
|
strcpy(item->key, key);
|
|
|
|
// Nastavíme hodnotu a zaradíme na začiatok zoznamu synoným
|
|
item->value = value;
|
|
item->next = (*table)[index];
|
|
(*table)[index] = item;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Získání hodnoty z tabulky.
|
|
*
|
|
* V případě úspěchu vrací funkce ukazatel na hodnotu prvku, v opačném
|
|
* případě hodnotu NULL.
|
|
*
|
|
* Při implementaci využijte funkci ht_search.
|
|
*/
|
|
float *ht_get(ht_table_t *table, char *key) {
|
|
// Vyhľadáme prvok
|
|
ht_item_t *item = ht_search(table, key);
|
|
|
|
if (item != NULL) {
|
|
// Ak existuje, vrátime pointer na hodnotu
|
|
return &(item->value);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* Smazání prvku z tabulky.
|
|
*
|
|
* Funkce korektně uvolní všechny alokované zdroje přiřazené k danému prvku.
|
|
* Pokud prvek neexistuje, funkce nedělá nic.
|
|
*
|
|
* Při implementaci NEPOUŽÍVEJTE funkci ht_search.
|
|
*/
|
|
void ht_delete(ht_table_t *table, char *key) {
|
|
int index = get_hash(key);
|
|
ht_item_t *item = (*table)[index];
|
|
ht_item_t *prev = NULL;
|
|
|
|
// Prechádzame zoznam a hľadáme prvok
|
|
while (item != NULL) {
|
|
if (strcmp(item->key, key) == 0) {
|
|
// Našli sme prvok na zmazanie
|
|
if (prev == NULL) {
|
|
// Je to prvý prvok v zozname
|
|
(*table)[index] = item->next;
|
|
} else {
|
|
// Je to prvok v strede/na konci zoznamu
|
|
prev->next = item->next;
|
|
}
|
|
|
|
// Uvoľníme pamäť
|
|
free(item->key);
|
|
free(item);
|
|
return;
|
|
}
|
|
prev = item;
|
|
item = item->next;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Smazání všech prvků z tabulky.
|
|
*
|
|
* Funkce korektně uvolní všechny alokované zdroje a uvede tabulku do stavu po
|
|
* inicializaci.
|
|
*/
|
|
void ht_delete_all(ht_table_t *table) {
|
|
// Prechádzame všetky položky tabuľky
|
|
for (int i = 0; i < HT_SIZE; i++) {
|
|
ht_item_t *item = (*table)[i];
|
|
|
|
// Postupne mažeme všetky prvky v zozname synoným
|
|
while (item != NULL) {
|
|
ht_item_t *next = item->next;
|
|
free(item->key);
|
|
free(item);
|
|
item = next;
|
|
}
|
|
|
|
// Inicializujeme položku na NULL
|
|
(*table)[i] = NULL;
|
|
}
|
|
}
|