⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 m.cpp

📁 该程序是模式识别课程里的K均值算法程序
💻 CPP
字号:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <math.h>

// 宏定义
#define  SUCCESS   1
#define  FAILURE   0
#define  TRUE   1
#define  FALSE   0
#define  MAXVECTDIM  20
#define  MAXPATTERN  20
#define  MAXCLUSTER  10
#define  SIZEVECTOR  2   //维数
#define  ResultsFile  "Results.txt"

char *f2a(double x, int width) //将x精确到小数点后width位
{
 char cbuf[255];
 char *cp;
 int i,k;
 int d,s;
cp=fcvt(x,width,&d,&s);/*函数名: fcvt
       功 能: 把一个浮点数转换为字符串
       用 法: char *fcvt(double value, int ndigit, int *decpt, int *sign);*/

if (s) 
{
 strcpy(cbuf,"-");
}
else 
{
 strcpy(cbuf," ");
} /* endif */
if (d>0) 
{
 for (i=0; i<d; i++) 
 {
  cbuf[i+1]=cp[i];
 } /* endfor */
 cbuf[d+1]=0;
 cp+=d;
 strcat(cbuf,".");
 strcat(cbuf,cp);
} 
else
{
 if (d==0)
 {
  strcat(cbuf,"0.");
  strcat(cbuf,cp);
 }
 else
 {
  k=-d;
  strcat(cbuf,".");
  for (i=0; i<k; i++)
  {
   strcat(cbuf,"0");
  } /* endfor */
  strcat(cbuf,cp);
 } /* endif */
} /* endif */
cp=&cbuf[0];
return cp;
}

// ***** Defined structures & classes *****
struct aCluster
{
 double       Center[MAXVECTDIM];
 int          Member[MAXPATTERN];  
 int          NumMembers;
};

struct aVector
{
 double       Center[MAXVECTDIM];
 int          Size;
};

class System
{
private:
 double  Pattern[MAXPATTERN][MAXVECTDIM+1];
 aCluster Cluster[MAXCLUSTER];
 FILE  *OutFile;     //存放结果文件
 int   NumPatterns;          // 数组的个数
 int   NumClusters;          // 类数相当于k
 void  DistributeSamples();  
 int   CalcNewClustCenters();
 double  EucNorm(int, int);    
 int   FindClosestCluster(int); 
                                        
public:
 system();
 int LoadPatterns(char *fname);     
 void InitClusters();                
 void RunKMeans();                  
 void ShowClusters();               
 void ShowCenters();
 void WriteResults();
 void CloseResults();
};

 void System::ShowCenters()
{
 int i;
 fprintf(OutFile,"\n求出新的聚类点为:\n");
 for (i=0; i<NumClusters; i++)
 {
  Cluster[i].Member[0]=i;
  fprintf(OutFile,"最合适的第%d个点为:ClusterCenter[%d]=(%2.1f,%2.1f)\n",i+1,i,Cluster[i].Center[0],Cluster[i].Center[1]);
 } /* endfor */
 fprintf(OutFile,"\n");
}

void System::WriteResults()
{
 if( ( OutFile = fopen(ResultsFile, "w" ) ) == NULL ) 
 { 
  printf( "输出结果文件打开失败!\npress any key to continue..." ); 
  getchar();
  exit(0);
 } 
}

void System::CloseResults()
{
 fclose(OutFile);
}

int System::LoadPatterns(char *fname)
{
 FILE *InFilePtr;
 int    i,j;
 double x;
 if((InFilePtr = fopen(fname, "r")) == NULL)
 {
  getchar();
  return FAILURE;
 }
 fscanf(InFilePtr, "%d", &NumPatterns); 
 fscanf(InFilePtr, "%d", &NumClusters);  
 for (i=0; i<NumPatterns; i++)           
 {
  for (j=0; j<SIZEVECTOR; j++)        
  {
   fscanf(InFilePtr,"%lg",&x);     
   Pattern[i][j]=x;
  } /* endfor */
 } /* endfor */
 fprintf(OutFile,"从文件中读取的%d个点的坐标数据如下:\n",NumPatterns);
 for (i=0; i<NumPatterns; i++)
 {
  fprintf(OutFile,"Pattern[%d]=(%2.1f,%2.1f)\n",i,Pattern[i][0],Pattern[i][1]);//2.1f
 } /* endfor */
 fprintf(OutFile,"\n");
 return SUCCESS;
}

void System::InitClusters()
{
 int i,j;
 fprintf(OutFile,"假设前%d个点为聚类点:\n",NumClusters);
 for (i=0; i<NumClusters; i++)
 {
  //Cluster[i].Member[0]=i;
  for (j=0; j<SIZEVECTOR; j++)
  {
   Cluster[i].Center[j]=Pattern[i][j];
  } /* endfor */
 } /* endfor */
for (i=0; i<NumClusters; i++)
 {
  fprintf(OutFile,"ClusterCenter[%d]=(%2.1f,%2.1f)\n",i,Cluster[i].Center[0],Cluster[i].Center[1]);
 } /* endfor */
 fprintf(OutFile,"\n");
}

void System::RunKMeans()
{
 int converged;
 int pass;
 pass=1;
 converged=FALSE;
 while (converged==FALSE)
 {
  fprintf(OutFile,"\nPASS=%d\n\n",pass++);
  DistributeSamples();//归类
  converged=CalcNewClustCenters();
  ShowCenters();
 } /* endwhile */
}

double System::EucNorm(int p, int c)    
{
 double dist,x;                      
 int i;                              
 char zout[128];
 char znum[40];
 char *pnum;

 pnum=&znum[0];
 strcpy(zout,"d=(");
fprintf(OutFile,"聚类点ClusterCenter[%d]与Pattern[%d]的距离为:",c,p);
 dist=0;
 for (i=0; i<SIZEVECTOR ;i++)
 {
  x=(Cluster[c].Center[i]-Pattern[p][i])*(Cluster[c].Center[i]-Pattern[p][i]);
  strcat(zout,f2a(x,1));
  if (i==0)strcat(zout,"+");
  dist += (Cluster[c].Center[i]-Pattern[p][i])*(Cluster[c].Center[i]-Pattern[p][i]);
 } /* endfor */
 fprintf(OutFile,"%s)",zout);
 return dist;
}

int System::FindClosestCluster(int pat)
{
 int i, ClustID;
 double MinDist, d;
 MinDist =9.9e+99;
 ClustID=-1;
 for (i=0; i<NumClusters; i++)
 {
  d=EucNorm(pat,i);
  fprintf(OutFile," = %2.1f\n",d);
  if (d<MinDist)
  {
   MinDist=d;
   ClustID=i;
  } /* endif */
 } /* endfor */
 if (ClustID<0)
 {
  fprintf(OutFile,"Aaargh");
  exit(0);
 } /* endif */
 return ClustID;
}

void System::DistributeSamples()
{
 int i,pat,Clustid,MemberIndex;   
 for (i=0; i<NumClusters;i++)
 {
  Cluster[i].NumMembers=0;
 }
 for (pat=0; pat<NumPatterns; pat++)   
 {
  Clustid= FindClosestCluster(pat);
  fprintf(OutFile,"发现点Patern[%d] 更接近于聚类点ClusterCenter[%d]\n\n",pat,Clustid);  
  MemberIndex=Cluster[Clustid].NumMembers;
  Cluster[Clustid].Member[MemberIndex]=pat;
  Cluster[Clustid].NumMembers++; 
 } /* endfor*/
}

int  System::CalcNewClustCenters()
{
 int ConvFlag,VectID,i,j,k;
 double tmp[MAXVECTDIM];
 char xs[255];
 char ys[255];
 char nc1[20];
 char nc2[20];
 char *pnc1;
 char *pnc2;
 
 pnc1=&nc1[0];
 pnc2=&nc2[0];
 ConvFlag=TRUE;
 fprintf(OutFile,"新的聚类点计算公式为:\n");
 for (i=0; i<NumClusters; i++)             
 {
  pnc1=itoa(Cluster[i].NumMembers,nc1,10);
  pnc2=itoa(i,nc2,10);
  strcpy(xs,"Cluster Center");
  strcat(xs,nc2);
  strcat(xs,"(1/");
  strcpy(ys,"(1/");
  strcat(xs,nc1);
  strcat(ys,nc1);
  strcat(xs,")(");
  strcat(ys,")(");
  for (j=0; j<SIZEVECTOR; j++)            
  {
   tmp[j]=0.0;
  } /* endfor */
  for (j=0; j<Cluster[i].NumMembers; j++) 
  {
   VectID=Cluster[i].Member[j];
   for (k=0; k<SIZEVECTOR; k++)       
   {
    tmp[k] += Pattern[VectID][k];   
    if (k==0)
    {
     strcat(xs,f2a(Pattern[VectID][k],1));
    }
    else
    {
     strcat(ys,f2a(Pattern[VectID][k],1));
    } /* endif */
   } /* endfor */
   if(j<Cluster[i].NumMembers-1)
   {
    strcat(xs,"+");
    strcat(ys,"+");
   }
   else
   {
    strcat(xs,")");
    strcat(ys,")");
   }
  } /* endfor */
  for (k=0; k<SIZEVECTOR; k++)          
  {
   tmp[k]=tmp[k]/Cluster[i].NumMembers;
   if (tmp[k] != Cluster[i].Center[k])
    ConvFlag=FALSE;
   Cluster[i].Center[k]=tmp[k];
  } /* endfor */
  fprintf(OutFile,"%s,\n",xs);
  fprintf(OutFile,"%s\n",ys);
 } /* endfor */
 fprintf(OutFile,"\n\n");
 for (i=0; i<NumClusters; i++)
 {
  fprintf(OutFile,"在聚类第%d个内的点有:\n",i+1);
  for (j=0; j<Cluster[i].NumMembers; j++) 
  {
   fprintf(OutFile,"  %d  ",Cluster[i].Member[j]);
  }
  fprintf(OutFile,"\n");
 }
 return ConvFlag;
}

void System::ShowClusters()
{
 int cl;
 for (cl=0; cl<NumClusters; cl++)
 {
  fprintf(OutFile,"\n聚类点%d坐标为:==>[%2.1f,%2.1f]\n", cl+1,Cluster[cl].Center[0],Cluster[cl].Center[1]);
 } /* endfor */
}

void main()
{
 System kmeans;
 char ReadFileName;
 kmeans.WriteResults();
 printf("请输入存放数据的文件名:");
 scanf("%s",&ReadFileName);
 if (kmeans.LoadPatterns(&ReadFileName)==FAILURE)
 {
  printf("对不起,文件%s不存在。\n",&ReadFileName);
  getchar();
  exit(0);
 }
 kmeans.InitClusters();
 kmeans.RunKMeans();
 kmeans.ShowClusters();
 kmeans.CloseResults();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -