Cod sursa(job #972541)

Utilizator mihai995mihai995 mihai995 Data 12 iulie 2013 00:49:01
Problema Hashuri Scor 0
Compilator c Status done
Runda Arhiva educationala Marime 6.65 kb
#include <stdlib.h>

const int _linear_hash_capacity[] = {
    0,
    3,
    7,
    13,
    29,
    53,
    97,
    193,
    389,
    769,
    1543,
    3079,
    6151,
    12289,
    24593,
    49157,
    98317,
    196613,
    393241,
    786433,
    1572869,
    3145739,
    6291469,
    12582917,
    25165843,
    50331653,
    100663319,
    201326611,
    402653189,
    805306457,
    1610612741,
};

typedef struct{
    void *key, *val;
} _linear_hash_node_t;

typedef struct{
    _linear_hash_node_t* hash;
    int* deleted_element;
    int size, cap;

    int (*compare_key)(void*, void*);
    int (*linear_hash_function)(void*);
    int (*probing_increment)(int);
} _linear_hash_t;

///PRIVATE FUNCTIONS
int _linear_hash_linear(int);
int _linear_hash_quadratic(int);
void _linear_hash_calibration(_linear_hash_t*);
int _linear_hash_keep_going(_linear_hash_t*, _linear_hash_node_t, void*, int);
_linear_hash_node_t* _linear_hash_supposed_position(_linear_hash_t*, void*, int);
_linear_hash_node_t* _linear_hash_find(_linear_hash_t*, void*);

///PUBLIC FUNCTIONS
void* linear_hash_new(int (*)(void*, void*), int (*)(void*), int);
void linear_hash_clear(_linear_hash_t*);
void linear_hash_delete(_linear_hash_t*);
int linear_hash_contains(_linear_hash_t*, void*);
int linear_hash_is_empty(_linear_hash_t*);
int linear_hash_get_size(_linear_hash_t*);
int linear_hash_get_capacity(_linear_hash_t*);
void linear_hash_insert(_linear_hash_t*, void*, void*);
void linear_hash_erase(_linear_hash_t*, void*);
void linear_hash_iterate(_linear_hash_t*, void (*)(void*, void*));

///PRIVATE FUNCTIONS
int _linear_hash_linear(int i){
    return 1;
}

int _linear_hash_quadratic(int i){
    return (i << 1) + 1;
}

void _linear_hash_calibration(_linear_hash_t* hash){
    int capacity, oldCapacity;

    oldCapacity = linear_hash_get_capacity(hash);
    hash -> cap++;
    capacity = linear_hash_get_capacity(hash);

    _linear_hash_node_t* area = hash -> hash;
    hash -> hash = malloc(capacity * sizeof(_linear_hash_node_t));
    linear_hash_clear(hash);

    int i;
    for (i = 0 ; i < oldCapacity ; i++)
        if (area[i].key != NULL && area[i].key != hash -> deleted_element)
            linear_hash_insert(hash, area[i].key, area[i].val);

    free(area);
}

int _linear_hash_keep_going(_linear_hash_t* hash, _linear_hash_node_t node, void* key, int insertORfind){
    if (node.key == NULL)
        return 0;

    if (node.key == hash -> deleted_element)
        return insertORfind;

    return hash -> compare_key(node.key, key) != 0;
}

_linear_hash_node_t* _linear_hash_supposed_position(_linear_hash_t* hash, void* key, int insertORfind){
    int cap = linear_hash_get_capacity(hash);
    int poz = hash -> linear_hash_function(key) % cap, i = 0;

    while (_linear_hash_keep_going(hash, hash -> hash[poz], key, insertORfind))
        poz = (poz + hash -> probing_increment(i++)) % cap;

    return (hash -> hash) + poz;
}


_linear_hash_node_t* _linear_hash_find(_linear_hash_t* hash, void* key){
    if (hash -> size == 0)
        return NULL;

    _linear_hash_node_t* poz = _linear_hash_supposed_position(hash, key, 1);
    return (poz -> key != NULL && poz -> key != hash -> deleted_element) ? poz : NULL;
}

///PUBLIC FUNCTIONS
void* linear_hash_new(int (*compare_key)(void*, void*), int (*linear_hash_function)(void*), int linearORquadratic_probing){
    _linear_hash_t* H = malloc( sizeof(_linear_hash_t) );

    H -> hash = NULL;
    H -> size = 0;
    H -> cap = 0;

    H -> compare_key = compare_key;
    H -> linear_hash_function = linear_hash_function;

    if (linearORquadratic_probing)
        H -> probing_increment = _linear_hash_quadratic;
    else
        H -> probing_increment = _linear_hash_linear;

    H -> deleted_element = malloc( sizeof(int) );

    return H;
}

void linear_hash_clear(_linear_hash_t* hash){
    memset(hash -> hash, 0, linear_hash_get_capacity(hash) * sizeof(_linear_hash_node_t));
    hash -> size = 0;
}

void linear_hash_delete(_linear_hash_t* hash){
    free(hash -> hash);
    free(hash -> deleted_element);
    free(hash);
}

int linear_hash_contains(_linear_hash_t* hash, void* key){
    return _linear_hash_find(hash, key) != NULL;
}

int linear_hash_is_empty(_linear_hash_t* hash){
    return hash -> size == 0;
}

int linear_hash_get_size(_linear_hash_t* hash){
    return hash -> size;
}

int linear_hash_get_capacity(_linear_hash_t* hash){
    return _linear_hash_capacity[ hash -> cap ];
}

void linear_hash_insert(_linear_hash_t* hash, void* key, void* val){
    _linear_hash_node_t* poz = _linear_hash_find(hash, key);

    if (poz != NULL && poz -> key != hash -> deleted_element){
        free(poz -> val);
        poz -> val = val;
        return;
    }

    if ( (hash -> size << 1) == _linear_hash_capacity[ hash -> cap ])
        _linear_hash_calibration(hash);

    hash -> size++;
    poz = _linear_hash_supposed_position(hash, key, 0);
    poz -> key = key;
    poz -> val = val;
}

void linear_hash_erase(_linear_hash_t* hash, void* key){
    _linear_hash_node_t* poz = _linear_hash_find(hash, key);

    if (poz == NULL)
        return;

    free(poz -> key);
    free(poz -> val);

    poz -> key = poz -> val = hash -> deleted_element;
}

void linear_hash_iterate(_linear_hash_t* hash, void (*iterate)(void*, void*)){
    int capacity = _linear_hash_capacity[ hash -> cap ], i;
    for (i = 0 ; i < capacity ; i++)
        if (hash -> hash[i].key != NULL && hash -> hash[i].val != hash -> deleted_element)
            iterate(hash -> hash[i].key, hash -> hash[i].val);
}

///ACTUAL CODE

int compara(void* a, void *b){
    return (*(int*)a) != (*(int*)b);
}

int hashFunction(void* a){
    return *(int*)a;
}

int* fint(int x){
    int* poz = malloc(sizeof(int));
    *poz = x;

    return poz;
}

char* sth(){
    return malloc(sizeof(char));
}

#include <stdio.h>

int main(){
    void* hash = linear_hash_new(compara, hashFunction, 0);
    FILE* fin = fopen("hashuri.in", "r");
    FILE* fout = fopen("hashuri.out", "w");

    int times, tip, x, *stn;

    fscanf(fin, "%d", &times);
    while (times--){
        fscanf(fin, "%d%d", &tip, &x);

        if (tip == 1)
            linear_hash_insert(hash, fint(x), sth());
        if (tip == 2){
            stn = fint(x);
            linear_hash_erase(hash, stn);
            free(stn);
        }
        if (tip == 3){
            stn = fint(x);
            fprintf(fout, "%d\n", linear_hash_contains(hash, stn));
            free(stn);
        }
    }

    fclose(fin);
    fclose(fout);

    return 0;
}