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

📄 isodata_iris.c

📁 经典的划分聚类算法
💻 C
字号:
#include<stdio.h>
#include<math.h>
#define ClassNumTimes 10
#define DataNum 150

typedef struct sample
{
	double x;
	double y;
	double z;
	double p;
} SAMPLE;

double distance(SAMPLE a,SAMPLE b)
{
	double d;
	double a1=a.x, a2=a.y,a3=a.z,a4=a.p;
	double b1=b.x, b2=b.y,b3=a.z,b4=b.p;

	d=sqrt((a1-b1)*(a1-b1)+(a2-b2)*(a2-b2)+(a3-b3)*(a3-b3)+(a4-b4)*(a4-b4));
	return d;
}

int MIN(double D[],int n)
{
	int i;
	int p=0;
	double fmin=D[0];
	for(i=1;i<n;i++)
	{
		if(D[i]<fmin) { fmin=D[i], p=i; }
	}
	return p;
}


int main()
{
	SAMPLE point[DataNum]={
2.1,3.2,1.4,0.2,
4.9,3.0,1.4,0.2,
4.7,3.2,1.3,0.2,
4.6,3.1,1.2,0.2,
2.0,3.6,1.4,0.2,
2.4,3.9,1.7,0.4,
4.6,3.4,1.4,0.3,
2.0,3.4,1.2,0.2,
4.4,2.9,1.4,0.2,
4.9,3.1,1.2,0.1,
2.4,3.7,1.2,0.2,
4.8,3.4,1.6,0.2,
4.8,3.0,1.4,0.1,
4.3,3.0,1.1,0.1,
2.8,4.0,1.2,0.2,
2.7,4.4,1.2,0.4,
2.4,3.9,1.3,0.4,
2.1,3.2,1.4,0.3,
2.7,3.8,1.7,0.3,
2.1,3.8,1.2,0.3,
2.4,3.4,1.7,0.2,
2.1,3.7,1.2,0.4,
4.6,3.6,1.0,0.2,
2.1,3.3,1.7,0.2,
4.8,3.4,1.9,0.2,
2.0,3.0,1.6,0.2,
2.0,3.4,1.6,0.4,
2.2,3.2,1.2,0.2,
2.2,3.4,1.4,0.2,
4.7,3.2,1.6,0.2,
4.8,3.1,1.6,0.2,
2.4,3.4,1.2,0.4,
2.2,4.1,1.2,0.1,
2.2,4.2,1.4,0.2,
4.9,3.1,1.2,0.1,
2.0,3.2,1.2,0.2,
2.2,3.2,1.3,0.2,
4.9,3.1,1.2,0.1,
4.4,3.0,1.3,0.2,
2.1,3.4,1.2,0.2,
2.0,3.2,1.3,0.3,
4.2,2.3,1.3,0.3,
4.4,3.2,1.3,0.2,
2.0,3.2,1.6,0.6,
2.1,3.8,1.9,0.4,
4.8,3.0,1.4,0.3,
2.1,3.8,1.6,0.2,
4.6,3.2,1.4,0.2,
2.3,3.7,1.2,0.2,
2.0,3.3,1.4,0.2,
7.0,3.2,4.7,1.4,
6.4,3.2,4.2,1.2,
6.9,3.1,4.9,1.2,
2.2,2.3,4.0,1.3,
6.2,2.8,4.6,1.2,
2.7,2.8,4.2,1.3,
6.3,3.3,4.7,1.6,
4.9,2.4,3.3,1.0,
6.6,2.9,4.6,1.3,
2.2,2.7,3.9,1.4,
2.0,2.0,3.2,1.0,
2.9,3.0,4.2,1.2,
6.0,2.2,4.0,1.0,
6.1,2.9,4.7,1.4,
2.6,2.9,3.6,1.3,
6.7,3.1,4.4,1.4,
2.6,3.0,4.2,1.2,
2.8,2.7,4.1,1.0,
6.2,2.2,4.2,1.2,
2.6,2.2,3.9,1.1,
2.9,3.2,4.8,1.8,
6.1,2.8,4.0,1.3,
6.3,2.2,4.9,1.2,
6.1,2.8,4.7,1.2,
6.4,2.9,4.3,1.3,
6.6,3.0,4.4,1.4,
6.8,2.8,4.8,1.4,
6.7,3.0,2.0,1.7,
6.0,2.9,4.2,1.2,
2.7,2.6,3.2,1.0,
2.2,2.4,3.8,1.1,
2.2,2.4,3.7,1.0,
2.8,2.7,3.9,1.2,
6.0,2.7,2.1,1.6,
2.4,3.0,4.2,1.2,
6.0,3.4,4.2,1.6,
6.7,3.1,4.7,1.2,
6.3,2.3,4.4,1.3,
2.6,3.0,4.1,1.3,
2.2,2.2,4.0,1.3,
2.2,2.6,4.4,1.2,
6.1,3.0,4.6,1.4,
2.8,2.6,4.0,1.2,
2.0,2.3,3.3,1.0,
2.6,2.7,4.2,1.3,
2.7,3.0,4.2,1.2,
2.7,2.9,4.2,1.3,
6.2,2.9,4.3,1.3,
2.1,2.2,3.0,1.1,
2.7,2.8,4.1,1.3,
6.3,3.3,6.0,2.2,
2.8,2.7,2.1,1.9,
7.1,3.0,2.9,2.1,
6.3,2.9,2.6,1.8,
6.2,3.0,2.8,2.2,
7.6,3.0,6.6,2.1,
4.9,2.2,4.2,1.7,
7.3,2.9,6.3,1.8,
6.7,2.2,2.8,1.8,
7.2,3.6,6.1,2.2,
6.2,3.2,2.1,2.0,
6.4,2.7,2.3,1.9,
6.8,3.0,2.2,2.1,
2.7,2.2,2.0,2.0,
2.8,2.8,2.1,2.4,
6.4,3.2,2.3,2.3,
6.2,3.0,2.2,1.8,
7.7,3.8,6.7,2.2,
7.7,2.6,6.9,2.3,
6.0,2.2,2.0,1.2,
6.9,3.2,2.7,2.3,
2.6,2.8,4.9,2.0,
7.7,2.8,6.7,2.0,
6.3,2.7,4.9,1.8,
6.7,3.3,2.7,2.1,
7.2,3.2,6.0,1.8,
6.2,2.8,4.8,1.8,
6.1,3.0,4.9,1.8,
6.4,2.8,2.6,2.1,
7.2,3.0,2.8,1.6,
7.4,2.8,6.1,1.9,
7.9,3.8,6.4,2.0,
6.4,2.8,2.6,2.2,
6.3,2.8,2.1,1.2,
6.1,2.6,2.6,1.4,
7.7,3.0,6.1,2.3,
6.3,3.4,2.6,2.4,
6.4,3.1,2.2,1.8,
6.0,3.0,4.8,1.8,
6.9,3.1,2.4,2.1,
6.7,3.1,2.6,2.4,
6.9,3.1,2.1,2.3,
2.8,2.7,2.1,1.9,
6.8,3.2,2.9,2.3,
6.7,3.3,2.7,2.2,
6.7,3.0,2.2,2.3,
6.3,2.2,2.0,1.9,
6.2,3.0,2.2,2.0,
6.2,3.4,2.4,2.3,
2.9,3.0,2.1,1.8}; //模式样本

	SAMPLE center[ClassNumTimes]; //聚类中心
	SAMPLE sd[ClassNumTimes];//standard deviation标准差向量
	double sdm[ClassNumTimes];//标准差向量中的最大分量(特征)
	int flag[150];//每个样本所属类别
	int count[ClassNumTimes];//各类别样本数
	double D[ClassNumTimes]; //样本到每个聚类中心的距离
	double Da[ClassNumTimes]; //各聚类域中诸样本与聚类中心间的平均距离
	double Dl; //全部模式样本对其相应聚类中心的总平均距离
	double Dc[ClassNumTimes]; //全部聚类中心的距离
	double a=0.5;//系数
	int t,t1,t2;
	int i,j;
	int n=0; //迭代次数
	int K=3,Nl=1,S=1,C=4,L=1,I=100; //预设参数
	int N=DataNum;
	int Nc=1;//分类次数

	for(i=0;i<ClassNumTimes;i++)
	{
		center[i]=point[i*N/K];
	}
	/*
	center[0]=point[0];
	for(i=1;i<ClassNum;i++)
	{
		center[i].x=-1;
		center[i].y=-1;
		center[i].z=-1;
		center[i].p=-1;
	}
	*/
	while(n<I)
	{
		n++;
		//按近邻原则聚类
		for(i=0;i<N;i++)
		{
			for(j=0;j<Nc;j++)
				D[j]=distance(point[i],center[j]);
			flag[i]=MIN(D,Nc);//注意
		}

		//赋初值
		for(j=0;j<Nc;j++)
		{
			count[j]=0;
			center[j].x=0;
			center[j].y=0;
			center[j].z=0;
			center[j].p=0;
			Da[j]=0;
			Dl=0;
		}

		//修正聚类中心
		for(i=0;i<N;i++)
		{
			j=flag[i];
			center[j].x+=point[i].x;
			center[j].y+=point[i].y;
			center[j].z+=point[i].z;
			center[j].p+=point[i].p;
			count[j]++;
		}
		for(j=0;j<Nc;j++)
		{
			if(count[j])
			{
				center[j].x/=count[j];
				center[j].y/=count[j];
				center[j].z/=count[j];
				center[j].p/=count[j];
			}
			printf("%d   %d \n",Nc,count[j]);
		}
		//计算各聚类域中诸样本与聚类中心间的平均距离
		//和全部模式样本对其相应聚类中心的总平均距离
		for(i=0;i<N;i++)
		{
			j=flag[i];
			Da[j]+=distance(point[i],center[j]);
		}
		for(j=0;j<Nc;j++)
		{
			Dl+=Da[j];
			Da[j]=Da[j]/count[j];
		}
		Dl=Dl/N;
		
		//进行分裂处理
		if(n!=I&&(Nc<=K/2||(Nc>K/2&&((fmod(n,2)!=0)&&Nc<2*K))))
		{
			for(j=0;j<Nc;j++)
			{
				sd[j].x=0;
				sd[j].y=0;
				sd[j].z=0;
				sd[j].p=0;
			}
			for(i=0;i<N;i++)
			{
				j=flag[i];
				sd[j].x+=(point[i].x-center[j].x)*(point[i].x-center[j].x);
				sd[j].y+=(point[i].y-center[j].y)*(point[i].y-center[j].y);
				sd[j].z+=(point[i].z-center[j].z)*(point[i].z-center[j].z);
				sd[j].p+=(point[i].p-center[j].p)*(point[i].p-center[j].p);
			}
			t=Nc;
			for(j=0;j<t;j++)
			{ 
				double u;
				sd[j].x=sqrt(sd[j].x/count[j]);
				sd[j].y=sqrt(sd[j].y/count[j]);
				sd[j].z=sqrt(sd[j].z/count[j]);
				sd[j].p=sqrt(sd[j].p/count[j]);
				if(sd[j].x>=sd[j].y)
					u=sd[j].x;
				else 
					u=sd[j].y;
				if(u<sd[j].z)	
					u=sd[j].z;
				if(u<sd[j].p)
					u=sd[j].p;
	         
				if(u==sd[j].x)
				{
					sdm[j]=sd[j].x;
					if(sdm[j]>S&&((Da[j]>Dl&&count[j]>2*(Nl+1))||Nc<=K/2))
					{
						center[Nc].x=center[j].x-a*sdm[j];
						center[Nc].y=center[j].y;
						center[Nc].z=center[j].z;
						center[Nc].p=center[j].p;
						center[j].x=center[j].x+a*sdm[j];
						Nc++;
					}
				}
				if(u==sd[j].y)
				{
					sdm[j]=sd[j].y;
					if(sdm[j]>S&&((Da[j]>Dl&&count[j]>2*(Nl+1))||Nc<=K/2))
					{
						center[Nc].x=center[j].x;
						center[Nc].z=center[j].z;
						center[Nc].p=center[j].p;
						center[Nc].y=center[j].y-a*sdm[j];
						center[j].y=center[j].y+a*sdm[j];
						Nc++;
					}
				}
				if(u==sd[j].z)
				{
					sdm[j]=sd[j].z;
					if(sdm[j]>S&&((Da[j]>Dl&&count[j]>2*(Nl+1))||Nc<=K/2))
					{
						center[Nc].x=center[j].x;
						center[Nc].y=center[j].y;
						center[Nc].p=center[j].p;
						center[Nc].z=center[j].z-a*sdm[j];
						center[j].z=center[j].z+a*sdm[j];
						Nc++;
					}
				}
				if(u==sd[j].p)
				{
					sdm[j]=sd[j].p;
					if(sdm[j]>S&&((Da[j]>Dl&&count[j]>2*(Nl+1))||Nc<=K/2))
					{
						center[Nc].x=center[j].x;
						center[Nc].z=center[j].z;
						center[Nc].y=center[j].y;
						center[Nc].p=center[j].p-a*sdm[j];
						center[j].p=center[j].p+a*sdm[j];
						Nc++;
					}
				}
			}
			if(Nc!=t) //进行了分裂处理  
				continue;
		}

		if(n==I) C=0; //最后一次迭代

		//进行合并处理
		t=0;
		t1=-1;
		t2=-1;
		for(i=1;i<Nc;i++)
		{
			for(j=0;j<i;j++)
			{
				Dc[t]=distance(center[i],center[j]);
				if(t>0&&Dc[t]<C&&Dc[t-1]>Dc[t])
					Dc[t]=Dc[t-1];
				else if(Dc[t]<C) { t1=j; t2=i; }//标记需要合并的
				t++;
			}
		}
		
		if(t1!=-1&&t2!=-1)
		{
			center[t1].x=(count[t1]*center[t1].x+count[t2]*center[t2].x)/(count[t1]+count[t2]);
			center[t1].y=(count[t1]*center[t1].y+count[t2]*center[t2].y)/(count[t1]+count[t2]);
			center[t1].z=(count[t1]*center[t1].z+count[t2]*center[t2].z)/(count[t1]+count[t2]);
			center[t1].p=(count[t1]*center[t1].p+count[t2]*center[t2].p)/(count[t1]+count[t2]);
			center[t2].x=-1;
			center[t2].y=-1;
			center[t2].z=-1;
			center[t2].p=-1;//还应该把count的值修改
			if(center[Nc-1].x!=-1&&center[Nc-1].y!=-1&&center[Nc-1].z!=-1&&center[Nc-1].p!=-1)
			{
				center[t2].x=center[Nc-1].x;
				center[t2].y=center[Nc-1].y;
				center[t2].z=center[Nc-1].z;
				center[t2].p=center[Nc-1].p;
			}
			Nc--;
		}
	}


	printf("the first class:\n");
	for(i=0;i<DataNum;i++)
	{
		if(flag[i]==0)
			printf("point[%d]=(%f,%f,%f,%f)\n",i,point[i].x,point[i].y,point[i].z,point[i].p);
	}
	printf("the class center is (%f,%f,%f,%f)\n",center[0].x,center[0].y,center[0].z,center[0].p);
	printf("\n");
	printf("the secend class:\n");
	for(i=0;i<DataNum;i++)
	{
		if(flag[i]==1)
			printf("point[%d]=(%f,%f,%f,%f)\n",i,point[i].x,point[i].y,point[i].z,point[i].p);
	}
	printf("the class center is (%f,%f,%f,%f)\n",center[1].x,center[1].y,center[1].z,center[1].p);
	printf("\n");
	printf("the third class:\n");
	for(i=0;i<DataNum;i++)
	{
		if(flag[i]==2)
			printf("point[%d]=(%f,%f,%f,%f)\n",i,point[i].x,point[i].y,point[i].z,point[i].p);
	}
	printf("the class center is (%f,%f,%f,%f)\n",center[2].x,center[2].y,center[2].z,center[2].p);
}

⌨️ 快捷键说明

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