k-均值聚类算法c语言版


#include 
< stdio.h >  
#include 
< math.h >
#define  TRUE            1
#define  FALSE           0 
int  N; // 数据个数
int  K; // 集合个数
int   *  CenterIndex; // 初始化质心数组的索引
double   *  Center; // 质心集合
double   *  CenterCopy; // 质心集合副本
double   *  AllData; // 数据集合
double   **  Cluster; // 簇的集合
int   *  Top; // 集合中元素的个数,也会用作栈处理

 
// 随机生成k个数x(0<=x<=n-1)作为起始的质心集合
void  CreateRandomArray( int  n,  int  k, int   *  center)
{
    
int  i = 0 ;
    
int  j = 0 ;    
    srand( (unsigned)time( NULL ) );
    
for ( i = 0 ;i < k; ++ i) // 随机生成k个数
    {
        
int  a = rand() % n;
        
// 判重
         for (j = 0 ;j < i;j ++ )
        {
            
if (center[j] == a) // 重复
            {
                
break ;
            }
        }
        
if (j >= i) // 如果不重复,加入
        {
            center[i]
= a;
        }
        
else
        {
            i
-- ;
            
// 如果重复,本次重新随机生成
        }
    }     
}
 
// 返回距离最小的质心的序号
int  GetIndex( double  value, double   *  center)
{
    
int  i = 0 ;
    
int  index = i; // 最小的质心序号
     double  min = fabs(value - center[i]); // 距质心最小距离
     for (i = 0 ;i < K;i ++ )
    {
        
if (fabs(value - center[i]) < min) // 如果比当前距离还小,更新最小的质心序号和距离值
        {
             index
= i;
             min
= fabs(value - center[i]);
        }
    }
    
return  index;
}
 
// 拷贝质心数组到副本
void  CopyCenter()
{
    
int  i = 0 ;
    
for (i = 0 ;i < K;i ++ )
    {
        CenterCopy[i]
= Center[i];
    }
}
// 初始化质心,随机生成法
void  InitCenter()
{
    
int  i = 0 ;
    CreateRandomArray(N,K,CenterIndex);
// 产生随机的K个<N的不同的序列
     for (i = 0 ;i < K;i ++ )
    {
        Center[i]
= AllData[CenterIndex[i]]; // 将对应数据赋值给质心数组
    }
    CopyCenter();
// 拷贝到质心副本
}
// 加入一个数据到一个Cluster[index]集合
void  AddToCluster( int  index, double  value)
{
    Cluster[index][Top[index]
++ ] = value; // 这里同进栈操作


// 重新计算簇集合
void  UpdateCluster()
{    
    
int  i = 0 ;
    
int  tindex;
    
// 将所有的集合清空,即将TOP置0
     for (i = 0 ;i < K;i ++ )
    {
        Top[i]
= 0 ;
    }
    
for (i = 0 ;i < N;i ++ )
    {
        tindex
= GetIndex(AllData[i],Center); // 得到与当前数据最小的质心索引
        AddToCluster(tindex,AllData[i]);         // 加入到相应的集合中 
    }
}
// 重新计算质心集合,对每一簇集合中的元素加总求平均即可
void  UpdateCenter()
{
    
int  i = 0 ;
    
int  j = 0 ;
    
double  sum = 0 ;
    
for (i = 0 ;i < K;i ++ )
    {
        sum
= 0 ;    
        
// 计算簇i的元素和
         for (j = 0 ;j < Top[i];j ++ )
         {
             sum
+= Cluster[i][j];
         }
        
if (Top[i] > 0 ) // 如果该簇元素不为空
        {
           Center[i]
= sum / Top[i]; // 求其平均值
        }
    }
}
// 判断2数组元素是否相等
int  IsEqual( double   *  center1 , double   *  center2)
{
    
int  i;
    
for (i = 0 ;i < K;i ++ )
    {
         
if (fabs(center1[i] != center2[i]))
         {
             
return  FALSE;
         }
    }
    
return  TRUE;
}
// 打印聚合结果
void  Print()
{
    
int  i,j;
    printf(
" -------------------------------------- " );
    
for (i = 0 ;i < K;i ++ )
    {
         printf(
" 第%d组: 质心(%f) " ,i,Center[i]);
          
for (j = 0 ;j < Top[i];j ++ )
          {
              printf(
" %f " ,Cluster[i][j]);
          }           
    }     
}
// 初始化聚类的各种数据
void  InitData()
{
    
int  i = 0 ;
    
int  a;
    printf(
" 输入数据个数: " );     
    scanf(
" %d " , & N);
    printf(
" 输入簇个数: " );     
    scanf(
" %d " , & K);    
    
if (K > N)
    {
        exit(
0 );
    }
    Center
= ( double   * )malloc( sizeof ( double ) * K); // 为质心集合申请空间
    CenterIndex = ( int   * )malloc( sizeof ( int ) * K); // 为质心集合索引申请空间
    CenterCopy = ( double   * )malloc( sizeof ( double ) * K); // 为质心集合副本申请空间
    Top = ( int   * )malloc( sizeof ( int ) * K); 
    AllData
= ( double   * )malloc( sizeof ( double ) * N); // 为数据集合申请空间
    Cluster = ( double   ** )malloc( sizeof ( double   * ) * K); // 为簇集合申请空间
    
// 初始化K个簇集合
     for (i = 0 ;i < K;i ++ )
    {
        Cluster[i]
= ( double   * )malloc( sizeof ( double ) * N);
        Top[i]
= 0 ;
    }
    printf(
" 输入%d数据: " ,N);
    
for (i = 0 ;i < N;i ++ )
    {
        scanf(
" %d " , & (a));
        AllData[i]
= a;
    }
    InitCenter();
// 初始化质心集合      
    UpdateCluster(); // 初始化K个簇集合
     
}
/*
算法描述:
K均值算法:
    给定类的个数K,将N个对象分到K个类中去,
    使得类内对象之间的相似性最大,而类之间的相似性最小。
*/
main()
{
    
int  Flag = 1 ; // 迭代标志,若为false,则迭代结束
     int  i = 0 ;
     InitData();
// 初始化数据      
      while (Flag) // 开始迭代
     {
         UpdateCluster();
// 更新各个聚类
         UpdateCenter(); // 更新质心数组
          if (IsEqual(Center,CenterCopy)) // 如果本次迭代与前次的质心聚合相等,即已收敛,结束退出
         {
             Flag
= 0 ;
         }
         
else // 否则将质心副本置为本次迭代得到的的质心集合
         {
             CopyCenter();
// 将质心副本置为本次迭代得到的的质心集合
         }
     }
     Print();
// 输出结果
     getchar();
     getchar();
     
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值