Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * Kostra programu pro 3. projekt IZP 2015/16
- *
- * Jednoducha shlukova analyza
- * Complete linkage
- * http://is.muni.cz/th/172767/fi_b/5739129/web/web/clsrov.html
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <assert.h>
- #include <math.h> // sqrt
- #include <limits.h> // INT_MAX
- /*****************************************************************
- * Ladici makra. Vypnout jejich efekt lze definici makra
- * NDEBUG, napr.:
- * a) pri prekladu argumentem prekladaci -DNDEBUG
- * b) v souboru (na radek pred #include <assert.h>
- * #define NDEBUG
- */
- #ifdef NDEBUG
- #define debug(s)
- #define dfmt(s, ...)
- #define dint(i)
- #define dfloat(f)
- #else
- // vypise ladici retezec
- #define debug(s) printf("- %s\n", s)
- // vypise formatovany ladici vystup - pouziti podobne jako printf
- #define dfmt(s, ...) printf(" - "__FILE__":%u: "s"\n",__LINE__,__VA_ARGS__)
- // vypise ladici informaci o promenne - pouziti dint(identifikator_promenne)
- #define dint(i) printf(" - " __FILE__ ":%u: " #i " = %d\n", __LINE__, i)
- // vypise ladici informaci o promenne typu float - pouziti
- // dfloat(identifikator_promenne)
- #define dfloat(f) printf(" - " __FILE__ ":%u: " #f " = %g\n", __LINE__, f)
- #endif
- /*****************************************************************
- * Deklarace potrebnych datovych typu:
- *
- * TYTO DEKLARACE NEMENTE
- *
- * struct obj_t - struktura objektu: identifikator a souradnice
- * struct cluster_t - shluk objektu:
- * pocet objektu ve shluku,
- * kapacita shluku (pocet objektu, pro ktere je rezervovano
- * misto v poli),
- * ukazatel na pole shluku.
- */
- struct obj_t {
- int id;
- float x;
- float y;
- };
- struct cluster_t {
- int size;
- int capacity;
- struct obj_t *obj;
- };
- /*****************************************************************
- * Deklarace potrebnych funkci.
- *
- * PROTOTYPY FUNKCI NEMENTE
- *
- * IMPLEMENTUJTE POUZE FUNKCE NA MISTECH OZNACENYCH 'TODO'
- *
- */
- /*
- Inicializace shluku 'c'. Alokuje pamet pro cap objektu (kapacitu).
- Ukazatel NULL u pole objektu znamena kapacitu 0.
- */
- void init_cluster(struct cluster_t *c, int cap)
- {
- assert(c != NULL);
- assert(cap >= 0);
- c->obj = malloc(sizeof(struct obj_t)*cap);
- c->capacity = cap;
- c->size = 0;
- // TODO
- }
- /*
- Odstraneni vsech objektu shluku a inicializace na prazdny shluk.
- */
- void clear_cluster(struct cluster_t *c)
- {
- free(c->obj);
- c->capacity=0;
- c->size=0;
- // TODO
- }
- /// Chunk of cluster objects. Value recommended for reallocation.
- const int CLUSTER_CHUNK = 10;
- /*
- Zmena kapacity shluku 'c' na kapacitu 'new_cap'.
- */
- struct cluster_t *resize_cluster(struct cluster_t *c, int new_cap)
- {
- // TUTO FUNKCI NEMENTE
- assert(c);
- assert(c->capacity >= 0);
- assert(new_cap >= 0);
- if (c->capacity >= new_cap)
- return c;
- size_t size = sizeof(struct obj_t) * new_cap;
- void *arr = realloc(c->obj, size);
- if (arr == NULL)
- return NULL;
- c->obj = arr;
- c->capacity = new_cap;
- return c;
- }
- /*
- Prida objekt 'obj' na konec shluku 'c'. Rozsiri shluk, pokud se do nej objekt
- nevejde.
- */
- void append_cluster(struct cluster_t *c, struct obj_t obj)
- {
- if(c->capacity==c->size)
- {
- resize_cluster(c,CLUSTER_CHUNK+c->size);
- }
- c->obj[c->size] = obj;
- c->size++;
- }
- /*
- Seradi objekty ve shluku 'c' vzestupne podle jejich identifikacniho cisla.
- */
- void sort_cluster(struct cluster_t *c);
- /*
- Do shluku 'c1' prida objekty 'c2'. Shluk 'c1' bude v pripade nutnosti rozsiren.
- Objekty ve shluku 'c1' budou serazny vzestupne podle identifikacniho cisla.
- Shluk 'c2' bude nezmenen.
- */
- void merge_clusters(struct cluster_t *c1, struct cluster_t *c2)
- {
- assert(c1 != NULL);
- assert(c2 != NULL);
- for(int i=0; i<c2->size; i++)
- {
- append_cluster(c1,c2->obj[i]);
- }
- sort_cluster(c1);
- }
- /**********************************************************************/
- /* Prace s polem shluku */
- /*
- Odstrani shluk z pole shluku 'carr'. Pole shluku obsahuje 'narr' polozek
- (shluku). Shluk pro odstraneni se nachazi na indexu 'idx'. Funkce vraci novy
- pocet shluku v poli.
- */
- int remove_cluster(struct cluster_t *carr, int narr, int idx)
- {
- assert(idx < narr);
- assert(narr > 0);
- clear_cluster(&carr[idx]);
- // TODO
- int i;
- for(i=idx;i<=narr;i++)
- {
- carr[i]=carr[i+1];
- }
- return narr-1;
- }
- /*
- Pocita Euklidovskou vzdalenost mezi dvema objekty.
- */
- float obj_distance(struct obj_t *o1, struct obj_t *o2)
- {
- assert(o1 != NULL);
- assert(o2 != NULL);
- float vzd;
- vzd=sqrt(pow((o1->x-o2->x),2)+pow((o1->y-o2->y),2));
- return vzd;
- // TODO
- }
- /*
- Pocita vzdalenost dvou shluku.
- */
- float cluster_distance(struct cluster_t *c1, struct cluster_t *c2)
- {
- assert(c1 != NULL);
- assert(c1->size > 0);
- assert(c2 != NULL);
- assert(c2->size > 0);
- float dis=0;
- float fdis=0;
- for(int i=0; i<c1->size;i++)
- {
- for(int j=0; j<c2->size;j++)
- {
- dis=obj_distance(&c1->obj[i],&c2->obj[j]);
- if(dis>fdis)
- {
- fdis=dis;
- }
- }
- }
- return fdis;
- // TODO
- }
- /*
- Funkce najde dva nejblizsi shluky. V poli shluku 'carr' o velikosti 'narr'
- hleda dva nejblizsi shluky. Nalezene shluky identifikuje jejich indexy v poli
- 'carr'. Funkce nalezene shluky (indexy do pole 'carr') uklada do pameti na
- adresu 'c1' resp. 'c2'.
- */
- void find_neighbours(struct cluster_t *carr, int narr, int *c1, int *c2)
- {
- assert(narr > 0);
- float dis=10000000;
- float fdis=dis;
- for(int i=0; i<narr;i++)
- {
- for(int j=i+1; j<narr;j++)
- {
- dis=cluster_distance(&carr[i],&carr[j]);
- if(dis<fdis)
- {
- fdis=dis;
- *c1=i;
- *c2=j;
- }
- }
- }
- // TODO
- }
- // pomocna funkce pro razeni shluku
- static int obj_sort_compar(const void *a, const void *b)
- {
- // TUTO FUNKCI NEMENTE
- const struct obj_t *o1 = a;
- const struct obj_t *o2 = b;
- if (o1->id < o2->id) return -1;
- if (o1->id > o2->id) return 1;
- return 0;
- }
- /*
- Razeni objektu ve shluku vzestupne podle jejich identifikatoru.
- */
- void sort_cluster(struct cluster_t *c)
- {
- // TUTO FUNKCI NEMENTE
- qsort(c->obj, c->size, sizeof(struct obj_t), &obj_sort_compar);
- }
- /*
- Tisk shluku 'c' na stdout.
- */
- void print_cluster(struct cluster_t *c)
- {
- // TUTO FUNKCI NEMENTE
- for (int i = 0; i < c->size; i++)
- {
- if (i) putchar(' ');
- printf("%d[%g,%g]", c->obj[i].id, c->obj[i].x, c->obj[i].y);
- }
- putchar('\n');
- }
- /*
- Ze souboru 'filename' nacte objekty. Pro kazdy objekt vytvori shluk a ulozi
- jej do pole shluku. Alokuje prostor pro pole vsech shluku a ukazatel na prvni
- polozku pole (ukalazatel na prvni shluk v alokovanem poli) ulozi do pameti,
- kam se odkazuje parametr 'arr'. Funkce vraci pocet nactenych objektu (shluku).
- V pripade nejake chyby uklada do pameti, kam se odkazuje 'arr', hodnotu NULL.
- */
- int load_clusters(char *filename, struct cluster_t **arr)
- {
- assert(arr != NULL);
- // TODO
- FILE *soubor;
- int pocet = 0;
- int id;
- float x,y;
- soubor = fopen(filename, "r");
- fscanf(soubor, "count=%d",&pocet);
- int i = 0;
- *arr = malloc(sizeof(struct cluster_t)*pocet); // alokuji si pole clusterù na pozadovanou velikosr
- for (i=0;i<pocet;i++)
- {
- init_cluster(&arr[0][i],50); //inicializu si [i]tý cluster o kapacitì max 1.
- fscanf(soubor, "%d %f %f", &id, &x, &y); // naètu id x y
- struct obj_t *objekt = malloc(sizeof(struct obj_t)); //vytvoøím si pomocný objekt obj_t a ulozim do nej ukazatele na misto v pameti, kde je na nej misto
- objekt->id=id; // priradim do pomocneho objektu ID
- objekt->x=x; // priradim do pomocneho objektu X
- objekt->y=y; // priradim do pomocneho objektu Y
- append_cluster(&arr[0][i],*objekt);
- //arr[0][i].obj = objekt; // pomocny objekt priradim do pole objetù v do clusteru
- // arr[0][i].size = 1; // velikost clusteru zmenim na 1
- print_cluster(&arr[0][i]);
- }
- //print_clusters(&arr[0][0],8);
- //print_clusters(&arr[0], 2);
- // free(objekt);
- //free()
- fclose(soubor);
- return i;
- }
- /*
- Tisk pole shluku. Parametr 'carr' je ukazatel na prvni polozku (shluk).
- Tiskne se prvnich 'narr' shluku.
- */
- void print_clusters(struct cluster_t *carr, int narr)
- {
- printf("Clusters:\n");
- for (int i = 0; i < narr; i++)
- {
- printf("cluster %d: ", i);
- print_cluster(&carr[i]);
- }
- }
- int main(int argc, char *argv[])
- {
- struct cluster_t *clusters;
- int pocetC=1;
- if(argc == 3)
- {
- pocetC=atoi(argv[2]);
- }
- int c1=0;
- int c2=0;
- int j=load_clusters(argv[1], &clusters);
- while(j>pocetC)
- {
- find_neighbours(clusters, j,&c1, &c2);
- merge_clusters(&clusters[c1],&clusters[c2]);
- j=remove_cluster(clusters,j,c2);
- }
- /*find_neighbours(clusters, j, &c1, &c2);
- //printf("%i %i",c1,c2);
- //printf("%f",cluster_distance(&clusters[0], &clusters[1]));
- //merge_clusters(&clusters[0],&clusters[5]);*/
- print_clusters(clusters, j);
- //j=remove_cluster(clusters,j,3);
- //clear_cluster(clusters);
- return 0;
- // TODO
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement