zoukankan      html  css  js  c++  java
  • 数据挖掘之K-中心点算法

    /*
    K-中心点算法思想: 将n个样本分成k个聚类,每个聚类里的样本关联性(相似性)较强。
    假如我现在有5个样本,分别是A,B,C,D,E,他们是二维向量。第一步是随机选择其中两个样本,就选A和B好了,并称他们为中心点,其他的称为非中心点,即C,D,E为非中心点。
    第二步,将非中心点归类到距离它最近的那个中心点的聚类。比如现在C归到A的聚类中,D归到B的聚类中,E归到A的聚类中,此时A,C,E是一个聚类,B,D是一个聚类。并计算总的代价(以距离来算)。第三步,用非中心点替换中心点,比如用C替换A,C变成了中心点,A变成了非中心点,然后再计算与之前的代价之差,如果小于0则可替换,否则不可替换。一直迭代下去,直到
    所有的中心点都没有发生替换。

    */
    #include<cstdio> #include<cstdlib> #include<iostream> #include<time.h> using namespace std; struct mem{ bool isMedoid; char symbol; }; struct Node; typedef struct Node *PNode; struct Node{ //节点 mem info; PNode link; }; struct LinkQueue{ //队列 PNode f; PNode r; }; typedef struct LinkQueue* PLinkQueue; PLinkQueue createEmptyQueue_link(){ //创建一个空的队列 PLinkQueue plqu; plqu=(PLinkQueue)malloc(sizeof(struct LinkQueue)); if(plqu!=NULL){ plqu->f=NULL; plqu->r=NULL; } else cout<<"Out of space"<<endl; return plqu; } int isEmptyQueue_link(PLinkQueue plqu){ return (plqu->f==NULL); } void enQueue_Link(PLinkQueue plqu,mem x){ PNode p; p=(PNode)malloc(sizeof(struct Node)); if(p==NULL) cout<<"Out of space"<<endl; else{ p->info=x; p->link=NULL; if(plqu->f==NULL) plqu->f=p; else plqu->r->link=p; plqu->r=p; } } void deQueue_link(PLinkQueue plqu){ PNode p; if(plqu->f==NULL) cout<<"Empty Queue"<<endl; else{ p=plqu->f; cout<<p->info.symbol; plqu->f=p->link; free(p); } } void showCase(double linjiebiao[5][5]){ int i,j; char tmp; cout<<"目前的邻接矩阵形式如下:"<<endl; cout<<"========================================="<<endl; cout<<" A B C D E "<<endl; for(i=0;i<5;i++){ tmp='A'+i; cout<<tmp; for(j=0;j<5;j++) cout<<" "<<linjiebiao[i][j]; cout<<endl; } cout<<"========================================"<<endl; } void arbStart(struct mem memlist[5]){ //随机选2个点作为中心点 int i,j; for(i=0;i<5;i++) if(memlist[i].isMedoid!=false) memlist[i].isMedoid=false; srand((unsigned)time(NULL)); i=rand()%5; memlist[i].isMedoid=true; j=rand()%5; while(j==i) j=rand()%5; memlist[j].isMedoid=true; } double distance(int j,int i,int k,double linjiebiao[5][5]){ //求解j,i,k中心店中较近的那个点的距离 if(linjiebiao[j][i]<linjiebiao[j][k]) return linjiebiao[j][i]; else return linjiebiao[j][k]; } double TC(int index[2],int i,int h,double linjiebiao[5][5]){ int j; double sum=0; int tmp; if(i==index[0]) tmp=index[1]; else if(i==index[1]) tmp=index[0]; for(j=0;j<5;j++){ sum+=distance(j,h,tmp,linjiebiao)-distance(j,index[0],index[1],linjiebiao); } return sum; } int smallest_distance_index(int index[2],int h,double linjiebiao[5][5]){ // 判断点h属于哪个中心点以形成簇 int i,result=index[0]; for(i=0;i<2;i++) if(linjiebiao[index[i]][h]<linjiebiao[index[0]][h]) result=index[i]; return result; } void showQueue(PLinkQueue pq){ cout<<"{"; while(!isEmptyQueue_link(pq)){ deQueue_link(pq); cout<<","; } cout<<''; cout<<"}"<<endl; } void reposition(mem memlist[5],double linjiebiao[5][5]){ //重新调整位置 int count,count1,h,i,k,holdi,holdh,index[2]; double tempdif; bool tmp; do{ count1=0; for(k=0;k<5;k++){ if(memlist[k].isMedoid==true){ //保存中心点 index[count1]=k; count1++; } } count=0; for(h=0;h<5;h++){ for(i=0;i<5;i++){ if(memlist[h].isMedoid==false&&memlist[i].isMedoid==true){ double dif=TC(index,i,h,linjiebiao); if(count==0){ tempdif=dif; holdi=i; holdh=h; count++; } else if(dif<tempdif){ tempdif=dif; holdi=i; holdh=h; count++; } } } } if(tempdif<0){ //小于0可替换 tmp=memlist[holdi].isMedoid; memlist[holdi].isMedoid=memlist[holdh].isMedoid; memlist[holdh].isMedoid=tmp; } else if(tempdif>=0) break; }while(1); } int main(){ int i,h,count; //i指代当前中心点,h指代可替换非中心点 int index[2]; //保存簇中心点 PLinkQueue pq[2]; pq[0]=createEmptyQueue_link(); //两个队列 pq[1]=createEmptyQueue_link(); double linjiebiao[5][5]={{0,1,2,2,3},{1,0,2,4,3},{2,2,0,1,5},{2,4,1,0,3},{3,3,5,3,0}}; struct mem memlist[5]={{false,'A'},{false,'B'},{false,'C'},{false,'D'},{false,'E'}}; showCase(linjiebiao); cout<<"期望得到的簇的数目暂定为2为例。"<<endl; cout<<endl<<endl<<endl; arbStart(memlist); cout<<"初始化后的中心点分布情况:"<<endl; int k; for(k=0;k<5;k++) cout<<memlist[k].symbol<<" "<<memlist[k].isMedoid<<endl; reposition(memlist,linjiebiao); cout<<endl<<endl<<endl; cout<<"经过K-中心点算法处理后的中心点分布情况:"<<endl; for(k=0;k<5;k++) cout<<memlist[k].symbol<<" "<<memlist[k].isMedoid<<endl; cout<<endl<<endl<<endl; count=0; for(i=0;i<5;i++){ if(memlist[i].isMedoid==true){ cout<<memlist[i].symbol<<"是最终得到的中心点"<<endl; enQueue_Link(pq[count],memlist[i]); index[count]=i; count++; } } for(h=0;h<5;h++){ if(memlist[h].isMedoid==false){ if(smallest_distance_index(index,h,linjiebiao)==index[0]) enQueue_Link(pq[0],memlist[h]); else if(smallest_distance_index(index,h,linjiebiao)==index[1]) enQueue_Link(pq[1],memlist[h]); } } cout<<"以以上两个中心点为中心的两个簇为:"<<endl; showQueue(pq[0]); showQueue(pq[1]); return 0; }
  • 相关阅读:
    asp .net 页面回车触发button 按钮事件
    Asp.netPost&Get转
    2012.8.16近期总结,1模态窗口回传重新被弹出2,清空缓存 3,
    面试感言
    2012.6.27近期总结,1.sql字符串转换(cast,CONVERT )调用wcf服务,关闭模态窗口刷新付页面
    self
    空指针
    枚举和结构体
    typedef
    指针
  • 原文地址:https://www.cnblogs.com/wust-ouyangli/p/6571894.html
Copyright © 2011-2022 走看看