usaa25/du5/a_station.c

161 lines
5.2 KiB
C

#include "a_station.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
// funkcia pre vytvorenie stanice
struct station* create_station(){
// allokujeme dynamicke v pamati (na heape) pomocou calloc; vsetky byty su inticializovane na 0
// tak tiez, allokujeme 1 krat
struct station* station = (struct station*)calloc(1,sizeof(struct station));
// double pointer: potrebujeme menit hodnotu; to je pointer na adresu ineho pointeru, a tot - na hodnotu.
// Defaultne referencia je na prvy pointer pol'a. Allokacia 10 krat (makros)
station->tracks = (struct car**)calloc(STATION_SIZE, sizeof(struct car*));
station->track_count = STATION_SIZE;
return station;
}
/// funkcia pre uvolnenie pamati
void destroy_station(struct station* station){
/// prechadzanie a uvolnenie jednotlyvich linked listov a ich prvkov
for(int i = 0; i<station->track_count; i++){
struct car* tmp = station->tracks[i];
while(tmp){
struct car* toFree = tmp;
tmp = tmp->next;
free(toFree);
}
}
// Mozeme uvolnit' array jednoducho, pretoze allokovali sme ho ako jeden 'kus'
free(station->tracks);
// uvolnenie stanice
free(station);
}
// Heshovacia funckica
int select_track(struct station* station, const char* target){
/// Pouzivame unsigned int pretoze cislo nesmie byt' zapornym
unsigned int hash = 0;
///iteracia po prvkoch kluca
for (int i = 0; i < strlen(target); i++)
/// Operator << je bitovy posun vl'avo. To iste ako vynasobit' nieco na 2^n.
///Napriklad <<6 je to iste ako * 2^6
{ hash += target[i] + (hash<<6) + (hash<<16) - hash;
}
/// Budeme mat' obrovske cislo na e vysledku, aj tak musime pouzit' mod velkos'ti pol'a.
/// Index musi byt' v intervale od 0 do n-1.
hash = hash %station->track_count;
return hash;
}
// Funkica pre vytvorenie noveho nodu v poli alebo zvacsenie capacity
void add_target_capacity(struct station* station,const char* target, int capacity){
// Dostaneme index
int res = select_track(station, target);
/// Pomocny pointer pre predchadzajucy
struct car* previous = NULL;
// adresa hlavy pre iteraciu. Prvok pod indexom. Vlasne, potrebuejeme vziat' adresu nodu, co robime.
struct car** ptr = &station->tracks[res];
//Berieme hodnotu - adresu pointeru pre iteraciu.
struct car* head = *ptr;
/// Prechadzame po linked listu
while(head){
//Ak destinacia nodu a hl'adane su rovnake, tak zvacsime capacitu nodu a prerusime program.
if(strcmp(head->value, target) == 0){
head->capacity += capacity;
return;
}
/// Prechadzame linked list
previous = head;
head = head->next;
}
// Ak sme vysli z cyklusu, to znamena ze polozka z prislusnym kl'ucom neexistuje a potrebuejeme vytvorit' nod.
//Vytvorame nod a prerdaime hodnoty
struct car* next = (struct car*)calloc(1, sizeof(struct car));
strcpy(next->value, target);
next->capacity = capacity;
//Ak posledny nod nie je NULL, ho nasledujucy bude vytvoreny
if(previous){
previous->next = next;
}
//Inak, zoznam prazdny a pointer pojde na adresu v pamati vytvoreneho
else{
*ptr = next;
}
}
/// Funkcia na dostanie capacity(hodnoty) kl'uca
int get_target_capacity(struct station* station,const char* target){
/// Index res podl'a kl'uca
int res = select_track(station, target);
/// Pointer na jednotlivy linked list
struct car** ptr = &station->tracks[res];
/// Berieme prvy nod v nom pre prechadzanie, cize berieme hodnotu double pointeru;
struct car* head = *ptr;
/// pokial' nie jie NULL
while (head)
// Ak najdeme v linked liste s prislusnym indexom nod z kl'com hl'adanym, tak vratime hodnotu tho nodu (capacitu)
{if(strcmp(head->value, target) == 0){
return head->capacity;
}
/// prechadzanie
head = head->next;
}
//Inak - nenajsli a vratime 0
return 0;
}
// Funkcia pre pocet vsetkych destinacii
int count_targets(struct station* station){
/// Ak je stanica NULL alebo pole NULL, vratime 0
/// || - logicky operator OR v C
if(station == NULL || station->tracks == NULL){
return 0;
}
int total = 0;
/// Iteracia po linked listoch pol'a
for(int i = 0; i<station->track_count; i++){
/// Pomocny pointer pre prechadzanie po jednotliyvych polozkach linked lista
struct car* ptr = station->tracks[i];
/// Incrementujeme pocet ak nie je to NULL, respektive je nejaka destinacia a prechadzame d'alej
while(ptr){
total++;
ptr = ptr->next;
}
}
/// Vratime pocet
return total;
}
/// Funkcia pre spocitanie vsetkych capacit (hodnot)
int count_capacity(struct station* station){
// Ak stanica je NULL alebo pole je NULL - vratime 0
if(station == NULL || station->tracks == NULL){
return 0;
}
int total = 0;
/// Iteracia po linked listoch v pole
for(int i = 0; i<station->track_count; i++){
/// Pomocny pointer pre prechadzanie
struct car* ptr = station->tracks[i];
while(ptr){
/// Pripocitame capacitu nodu a pojdeme d'alej
total += ptr->capacity;
ptr = ptr->next;
}
}
/// Vratime sucet
return total;
}