おいも貴婦人ブログ

生物系博士課程満期退学をしたAIエンジニアのブログ。

C言語:階層的クラスタリング、階層的クラスター分析(完)

とりあえず完成しましたが読むに値しないコードです。やっぱりコードを描く上で難しいのが変数の名前と注釈だと思います。とりあえず、仕様は前の記事の通りになりました。

これから、たくさんのコードを描いていきたいと思います。
以下コードです。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

#define MAX 1000

//------------  struct data  --------------
struct dataline{
    double data;
    struct dataline *next;
};

struct clust{
    int num;
    double length;
    struct dataline *vec;
    struct clust *right;
    struct clust *left;
};

struct line{
    int point;
    struct line *next;
};
struct intmat{
    struct dataline *intlist;
    struct intmat *next;
};
//------------ define function ------------
struct clust *clustalloc(void);
struct line *linealloc(void);
struct clust *makeclust(struct clust **root,int i,int j,double length,int num);
double length(struct clust *c1,struct clust *c2);
void printclust(struct clust *root);
void append(struct line *end,int point);
void del(struct line *head,int point);
struct dataline *makevec(struct dataline *list1,struct dataline *list2);
struct dataline *intsplit(char *s1,int *num);
struct dataline *intalloc(void);
struct intmat *matalloc(void);
struct intmat *readdata(int argc,char *argv[],int *datalength);
double pointlength(struct dataline *list1,struct dataline *list2);

//------------------------------
int main(int argc,char *argv[]){
    int num=0,i,datalength;
    struct clust *mat[MAX],*root,*head,*newc;
    struct line *lp,*rootline,*headline,*end,*lp2,*lp3,*start,*p;
    struct intmat *data,*headmat,*matp;
    struct dataline *pline;
    double min,d;
    int minpair[2];
    
    root=clustalloc();
    rootline=linealloc();
    headline=NULL;
    
    data=readdata(argc,argv,&datalength);
    matp=data;
    i=0;
    while(matp!=NULL){
        pline=matp->intlist;
        while(pline!=NULL){
            pline=pline->next;
        }
        matp=matp->next;
        i++;
    }

    matp=data;
    for(num=0;num<argc-1;num++){
        pline=matp->intlist;
        mat[num]=clustalloc();
        mat[num]->num=num;
        mat[num]->length=0;
        mat[num]->vec=matp->intlist;
        mat[num]->right=mat[num]->left=NULL;
        lp=linealloc();
        lp->next=headline;
        lp->point=num;
        headline=lp;
        while(pline!=NULL){
            pline=pline->next;
        }
        matp=matp->next;
    }
    
    end=lp;
    while(lp!=NULL){
        lp=lp->next;
    }
    lp=end;
    while(lp->next->next!=NULL){
        min=pointlength(mat[lp->point]->vec,mat[lp->next->point]->vec);
        minpair[0]=lp->point;
        minpair[1]=lp->next->point;
        lp2=lp;
        while(lp2!=NULL){
            lp3=lp2->next;
            while(lp3!=NULL){
                d=pointlength(mat[lp2->point]->vec,mat[lp3->point]->vec);
                if(d<=min){
                
                    minpair[0]=lp2->point;
                    minpair[1]=lp3->point;
                    newc=makeclust(mat,minpair[0],minpair[1],d,num);
                    min=d;
                }
                lp3=lp3->next;
   
                                    
            }

            lp2=lp2->next;

        }
        p=end;

        del(lp,minpair[0]);
        del(lp,minpair[1]);
        append(lp,num);
        mat[num]=newc;
        num++;
    }
    
    p=end;
    root=makeclust(mat,p->point,p->next->point,pointlength(mat[p->point]->vec,mat[p->next->point]->vec),num);
    printclust(root);
    while(p!=NULL){
        p=p->next;
    }
        
    return 0;
}
//---------------------
void printclust(struct clust *root){
    static int num=0;
    int i;
    struct clust *p;
    p=root;
    printf("%d:%lf\n",p->num,p->length);
    if(p->right!=NULL){
        for(i=0;i<num;i++)printf(" ");
        printf("right->");
        printclust(p->right);
        num++;
    }
    if(p->left!=NULL){
        for(i=0;i<num;i++)printf(" ");
        printf("left->");
        printclust(p->left);
        num++;
    }
    return;
}


void append(struct line *end,int point)
{
    struct line *lp,*new,*lp2;
    new=linealloc();
    new->point=point;
    lp=end;
    while(lp!=NULL){
        lp2=lp;
        lp=lp->next;
    }
    lp2->next=new;
}
void del(struct line *head,int point){
    struct line *p,*end,*old,*tp,*p2,*p3;
    p=head;
    
    while(p!=NULL){
        if(p->point==point){
            if(p==head){
                p2=head;
                while(p2->next!=NULL){
                    p2->point=p2->next->point;
                    p3=p2;
                    p2=p2->next;
                }
                free(p3->next);
                p3->next=NULL;
                return ;
            }                
            end=old->next;
            old->next=end->next;
            return;
        }
        old=p;
        p=p->next;
    }
}
struct clust *makeclust(struct clust **root,int i,int j,double length,int num){
    struct clust *newclust;
    newclust=clustalloc();
    newclust->num=num;
    newclust->right=root[i];
    newclust->left=root[j];
    newclust->vec=makevec(root[i]->vec,root[j]->vec);
    newclust->length=length;
    return newclust;
}
struct intmat *readdata(int argc,char *argv[],int *datalength)
{
    struct intmat *data,*matp,*head;
    struct dataline *line,*p;
    int i;
    FILE *rfp;
    char buf[256];
    head=NULL;

    printf("read:");
    for(i=1;i<argc;i++){
        printf("%s ",argv[i]);
        if((rfp=fopen(argv[i],"r"))==NULL){
            printf("%s is not readable\n",argv[i]);
            exit(1);
        }
        while(fgets(buf,256,rfp)!=NULL)
            line=intsplit(buf,datalength);
        p=line;
        data=matalloc();
        data->next=head;
        data->intlist=line;
        head=data;
    }
    puts("");
    return data;
}


double pointlength(struct dataline *list1,struct dataline *list2)
{
    double out=0;
    struct dataline *p1,*p2;
    p1=list1;
    p2=list2;
    while(p1!=NULL){
        out+=pow((p1->data-p2->data),2);
        p1=p1->next;
        p2=p2->next;
    }
    return sqrt(out);
}
void split(char *s1){
    char *temp;
    char *s2=" ";
    temp=strtok(s1,s2);
    while(temp!=NULL){
        printf("%s\n",temp);
        temp=strtok(NULL,s2);
    }
}
struct dataline *intsplit(char *s1,int *num){
    char *temp;
    char *s2=" ";
    int i;
    int j=0;
    struct dataline *p,*head;
    
    temp=strtok(s1,s2);
    head=NULL;
    while(temp!=NULL){
        i=atoi(temp);
        temp=strtok(NULL,s2);
        
        p=intalloc();
        p->next=head;
        p->data=i;
        head=p;
        j++;
    }
    *num=j;
    return p;
}
struct dataline *makevec(struct dataline *list1,struct dataline *list2){

    struct dataline *out,*p,*p2,*head;
    p=list1;
    p2=list2;
    head=NULL;
    
    while(p!=NULL){
        out=intalloc();
        out->data=(p->data+p2->data)/2;
        out->next=head;
        head=out;
        p=p->next;
        p2=p2->next;
    }
    return head;
}

//-----memory  allocate---------------------------------------
struct dataline *intalloc(void)
{
    return (struct dataline *)malloc(sizeof(struct dataline));
}
struct intmat *matalloc(void)
{
    return (struct intmat *)malloc(sizeof(struct intmat));
}
struct clust *clustalloc(void)
{
    return (struct clust *)malloc(sizeof(struct clust));
}
struct line *linealloc(void)
{
    return (struct line *)malloc(sizeof(struct line));
}