计算智能——K-means聚类算法C语言代码

news/2024/10/18 16:49:47/


  K-means聚类算法 也称K均值聚类算法 是一种迭代求解的聚类分析算法,其步骤是随机选取K个对象作为初始的聚类中心,然后计算每个对象与各个种子聚类中心之间的距离,把每个对象分配给距离它最近的聚类中心。

1. K-Means原理

  


上图a表示最初的对象点的样本,在图b中我们首先假定k=2,即在样本空间区域随机选取两个坐标点,然后通过计算每个点与两个之间的距离大小分为两个类别,如图c所示,接着在每一组对象点当中计出中心坐标点,这样我们就得到了图d的两个新的坐标点,通过如此反复的迭代过程,最后结果趋于稳定,最终我们得到的两个类别如图f。

2.编程思路

首先我假设生成一个6*6的二维数组,通过产生随机数0/1的方式,随机产生一个带数值的二维数组,这些数值表示的是这是第几个对象点,如06,则表示第6个点为对象点,如果是00则表示该坐标没有对象点。

然后设定两个初始的坐标点,用来进行第一次的分类,通过计算每个对象点和两个坐标点的距离,划分成了2个类别—d1,d2数组。

接着分别在d1数组和d2数组中找出该组对象点的中心值坐标,这样就可以得到新的两个坐标点。

最后通过迭代算法,找出不再变化的坐标点则完成分类。

3.代码实现

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include <math.h>
main()
{
    int i,j;
    int a[6][6];
    srand(time(0));//以时间为种子,每次生成不同的数
    for(i=0;i<6;i++)
    {   
      for(j=0;j<6;j++)
        //随机生成0/1 
        a[i][j]=0+rand()%2;//rand()生成数的范围在[a,b)写成:a[i]=a+rand()%(b-a); 
    }

    for(i=0;i<6;i++)
       for(j=0;j<6;j++){
           if(a[i][j]==1)
             a[i][j]=i*6+j+1;
       }
    printf(" 随机生成对象点:\n");   
    for(i=0;i<6;i++)
       for(j=0;j<6;j++){
           if(j!=5)
            printf(" %02d  ",a[i][j]);
           else
             printf(" %02d  \n",a[i][j]);
       }
       printf("\n");printf("\n");
       
    int x[2]={1,1};//提前选取两个初始点 
    int y[2]={4,4};
    int x1,x2,y1,y2;    
    
    int d1[36]={0};//通过点之间的距离分为两组聚集数组 
    int d2[36]={0};
    int k=0;
    int l=0;
          for(i=0;i<6;i++)
             for(j=0;j<6;j++){
                 if(a[i][j]!=0){
                     if(sqrt((i-x[0])*(i-x[0])+(j-x[1])*(j-x[1]))<sqrt((i-y[0])*(i-y[0])+(j-y[1])*(j-y[1]))){
                     d1[k]=a[i][j];
                     k++;
                 }
                     else{
                     d2[l]=a[i][j];
                     l++;
                 }
                 }
             }
    printf("通过两个初始点分类成两个聚集数组:\n");
    printf("数组一:");
    for(i=0;i<k;i++)
            printf("%d  ",d1[i]);
    printf("\n");
    printf("数组二:");
    for(i=0;i<l;i++)
            printf("%d  ",d2[i]);
     
     printf("\n");
    int o=0;int p=0;
    int q;//每个点的行号       
    for(i=0;i<k;i++){
        q=(d1[i]-1)/6;
        o=q+o;
        p=d1[i]-q*6-1+p;
    } 
    x[0]=o/k;x[1]=p/k;
    o=0;p=0; 
     for(i=0;i<l;i++){
        q=(d2[i]-1)/6;
        o=q+o;
        p=d2[i]-q*6-1+p;
    } 
    y[0]=o/l;y[1]=p/l;
    printf("\n");printf("\n");
    printf("根据两个已分类的数组中心值新生成的两个坐标点:\n"); 
    printf("%d,%d   ",x[0],x[1]);
    printf("%d,%d \n\n",y[0],y[1]);
    
    while(1){
    x1=x[0];x2=x[1];y1=y[0];y2=y[1];
        for(i=0;i<36;i++){
        d1[i]=0;d2[i]=0;}
        k=0;
        l=0;
        for(i=0;i<6;i++)
             for(j=0;j<6;j++){
                 if(a[i][j]!=0){
                     if(sqrt((i-x[0])*(i-x[0])+(j-x[1])*(j-x[1]))<sqrt((i-y[0])*(i-y[0])+(j-y[1])*(j-y[1]))){
                     d1[k]=a[i][j];
                     k++;
                 }
                     else{
                     d2[l]=a[i][j];
                     l++;
                 }
                 }
             }
           o=0;p=0;q=0;
           for(i=0;i<k;i++){
        q=(d1[i]-1)/6;
        o=q+o;
        p=d1[i]-q*6-1+p;
    } 
    x[0]=o/k;x[1]=p/k;
    o=0;p=0;q=0; 
     for(i=0;i<l;i++){
        q=(d2[i]-1)/6;
        o=q+o;
        p=d2[i]-q*6-1+p;
    } 
    y[0]=o/l;y[1]=p/l;
    printf("根据两个已分类的数组中心值新生成的两个坐标点:\n"); 
    printf("%d,%d   ",x[0],x[1]);
    printf("%d,%d \n\n",y[0],y[1]);    

    if(x1==x[0] && x2==x[1] && y1==y[0] && y2==y[1]){
        printf("已找到最终的两个坐标点!");
        break;
    }
    }
     
    
}

4.运行结果展示

 

 

 

 

 


http://www.ppmy.cn/news/714126.html

相关文章

用c语言编写程序,求∑(k=1~100)k+∑(k=1~50)k2,c语言程序,求(100∑k=1 k)+(50∑k=1 k^2)+(10∑k=1 1/k) 这...

满意答案 myhso 2015.10.31 采纳率&#xff1a;54% 等级&#xff1a;8 已帮助&#xff1a;1060人 主函数main没有定义&#xff0c;在c语言中 两个整数相除返回整数 1/1 结果为 1 &#xff0c;1/2,1/3结果为0,所以 ss1/k要改为ss1.0/k ,最终的结果有小数 s不能定义为int整数&…

c语言全局变量SQR,c语言a/=SQR(k+m);是什么意思?

满意答案 NightmareJJ 2013.03.16 采纳率&#xff1a;47% 等级&#xff1a;12 已帮助&#xff1a;11233人 先看第一个 main() // 主函数 {printf("%ld\n", fun(3));} //输出fun(3)这个函数的返回值&#xff0c;3就是下一个 //函数中的n 值。 long fun (int n) //定…

【C语言】C语言实现矩阵k次幂 (模拟手工计算过程,简单逻辑)

运用递归实现k次幂运算&#xff0c;模拟手工计算 注释掉的输出部分便于调试过程中检查使用 使用说明&#xff1a;输入一个数字k&#xff0c;计算矩阵的k次幂&#xff0c;输出原矩阵以及其k次幂矩阵 矩阵的k次幂可用于以邻接矩阵存储的图的算法中&#xff0c;具体原理涉及到离…

5.21-----c语言冒泡排序--谁考了第K名

题目&#xff1a; 算法描述&#xff1a; 先创建2个数组&#xff0c;然后将学号&#xff0c;成绩都存在数组里面&#xff0c;然后里要冒泡排序法将学号&#xff0c;成绩按从小到大进行排序&#xff0c;然后输出第k名的成绩&#xff08;数组下标为k-1&#xff09;的。 #include&…

运用折半查找算法在一个有序数组中查找具体的某个数值k(c语言)

实现功能 在一个有序数组中&#xff0c;查找想要查找的某个具体数值。 如何实现 主要逻辑&#xff1a; 运用折半查找算法&#xff1a;设置中间值、左变量、右变量&#xff0c;通过比较大小不断将数组查找范围折半缩小&#xff0c;直至找到想要查找的数值k。 代码 #includ…

c语言将数组元素循环右移k位,把一个含有N个元素的数组循环右移K位

普通解法&#xff1a; 可以每次将数组中的元素右移一位&#xff0c;循环K次。每个元素右移N位后都会回到自己的位置上。因此&#xff0c;如果K > N&#xff0c;右移K-N之后的数组序列跟右移K位的结果是一样的。进而可得出一条通用的规律&#xff1a;右移K位之后的情形&#…

用分治法寻找第k小的值(C语言实现)

经典方法&#xff1a; #include<stdio.h> #include<stdlib.h> int min(int* A, int start, int end) {if (start end)return A[start];else{int min1, min2, mid;mid (start end) / 2;min1 min(A,start, mid);min2 min(A,mid 1, end);if (min1 < min2)re…

C语言学习笔记: i < j < k 的操作

表达式i < j < k在C语言中是合法的&#xff0c;但是它不是你所期望的意思。因为&#xff1c;运算符是左结合的&#xff0c; 所以这个表达式等价于(i < j) < k. 换句话说&#xff0c; 表达式首先检测l.是否小千j, 然后用比较后产生的结果1或0来和K进行比较。 表达式…