namespace K_means
{
public class Kmeans
{
double[,] inPut;//数据
int k;//类别数
int Num;//文件数
int sub;//特征值数
int[] groupNum ;//各组数目
public Kmeans(double[,] input)
{
inPut = input;
Num = input.GetLength(0);
sub = input.GetLength(1);
k = (int)Math.Sqrt(Num) + 1;
groupNum = new int[k];
}
public int[,] GetProcess()
{
double[,] tmpCenter = new double[k, sub];
for (int i = 0; i < k; i++)
for (int j = 0; j < sub; j++)
tmpCenter[i, j] = inPut[i, j];
double[,] preCenter = new double[k, sub];
int[,] resultP ;//= new int[k, Num];
while (true)
{
resultP = new int[k, Num];
#region //清空各组的数目
for (int i = 0; i < k; i++)
{
groupNum[i] = 0;
}
#endregion
#region //根据点到质心的距离,将点放到不同的组中
for (int i = 0; i < Num; i++)
{
double tmpDis = 0.0;
int index = 0;
for (int j = 0; j < k; j++)
{
double tmpIn = 0.0;
for (int m = 0; m < sub; m++)
{
tmpIn += Math.Pow((inPut[i, m] - tmpCenter[j, m]), 2);
}
if (j == 0)
{
tmpDis = tmpIn;
index = 0;
}
else
{
if (tmpDis > tmpIn)
{
tmpDis = tmpIn;
index = j;
}
}
}
int groupKnum = groupNum[index];
resultP[index, groupKnum] = i+1;
groupNum[index]++;
}
#endregion
#region //保存质心
for (int i = 0; i < k; i++)
for (int j = 0; j < sub; j++)
preCenter[i, j] = tmpCenter[i, j];
#endregion
#region //确定新质心
for (int i = 0; i < k; i++)
{
int kNum=groupNum[i];
if (kNum > 0)
{
for (int j = 0; j < sub; j++)
{
double tmp = 0.0;
for (int m = 0; m < kNum; m++)
{
int groupIndex = resultP[i,m]-1;
tmp += inPut[groupIndex, j];
}
tmpCenter[i, j] = tmp / kNum;
}
}
}
#endregion
#region //判断质心是否变化
bool judge = true;
for (int i = 0; i < k; i++)
{
for (int j = 0; j < sub; j++)
{
judge = judge && (preCenter[i,j]==tmpCenter[i,j]);
}
}
if (judge)
{
break;
}
#endregion
}
return resultP;
}
}
}