📄 patternview.cpp
字号:
}
for(k = 0; k < iShuMu; k++)
{
samplecen[k].cx = sumcencx[k]/sumnum[k];
samplecen[k].cy = sumcency[k]/sumnum[k];
}
//第四步:判断迭代算法的结束
for(k = 0; k < iShuMu; k++)
{
if(samplecen[k].cx != oldprecen[k].cx || samplecen[k].cy != oldprecen[k].cy )
{
oldprecen[k] = samplecen[k];
//初始化样本中心点是否显示
samplecen[k].fseek = true;
OnDraw(pDC);
//显示文本
CFont MyFont;
MyFont.CreateFont(25,0,0,0,400,FALSE,FALSE,0,
ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,DEFAULT_PITCH|FF_SWISS,"楷体_GB2312");
CFont* pOldFont=pDC->SelectObject(&MyFont);
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(RGB(255,0,255));
char number1[80];
char number2[80];
sprintf(number1,"迭代次数:%d",n - 1);//显示" 第n - 1次迭代!";number1为要输出字符的CString对象
sprintf(number2,"指定的聚类中心数:k=%d",iShuMu);
pDC->TextOut(550,10,number1);
pDC->TextOut(250,10,number2);
MyFont.DeleteObject();
//是否显示中心点
bshowcen = true;
Sleep(50);
goto lab1;
}
}
delete [] oldprecen;
bshowcen = false;
}
void CPatternView::OnIsodata()
{
// TODO: Add your command handler code here
bshowcen = true;
CDC* pDC;
pDC=GetDC();
//局部变量
int i, j ,k;
SampleDot *oldprecen;
oldprecen = new SampleDot[15];
//初始化所有样本点的颜色
for(i=0;i < iShuMu;i++)
{
for(j=0;j < iDianShu;j++)
{
samplenum[i*iDianShu+j].colorvalue = RGB(255,0,0);
}
}
//初始化样本中心点是否显示
for(i=0;i < 10;i++)
{
samplecen[i].fseek = true;
}
//////////////////////////////////////////////////////////
//第一步:初始化预选参数
int iK, iL, iI ,iSetaN;
float fSetaS, fSetaC;
// 创建对话框
CDlgIsodata dlgPara;
// 显示对话框,提示用户设定用户参数
if (dlgPara.DoModal() != IDOK)
{
// 返回
return;
}
iK = dlgPara.m_iK;
iSetaN = dlgPara.m_iSetaN;
fSetaS = dlgPara.m_fSetaS;
fSetaC = dlgPara.m_fSetaC;
iL = dlgPara.m_iL;
iI = dlgPara.m_iI;
//迭代次数的记录值
int iterativenum = -1;
//记录中心点数规定值
int iknum = iK;
// 删除对话框
delete dlgPara;
//初始化前iK个中心点
for(i=0;i < iK;i++)
{
oldprecen[i] = samplenum[i];
}
//////////////////////////////////////////////////////////
//第二步:分配样本点(将所有样本点分配给最近的iK个聚类)
step2:
//迭代次数的累计
iterativenum++;
float olddis , newdis;
/////////////////////////////////////////////////////////////////////////////////////////////////
//开始搜索,初始化所有未归类的样本点
for(i=0;i<iShuMu;i++)
{
for(j=0;j<iDianShu;j++)
{
samplenum[i*iDianShu+j].fseek = true;
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
for(i=0;i<iShuMu * iDianShu;i++)//将所有的点按最小距离分成iK类
{
olddis = 2000;
for(j=0;j < iK;j++)
{
newdis = sqrt((samplenum[i].cx - oldprecen[j].cx) * (samplenum[i].cx - oldprecen[j].cx)
+ (samplenum[i].cy - oldprecen[j].cy) * (samplenum[i].cy - oldprecen[j].cy));
if(newdis < olddis)
{
olddis = newdis;
samplenum[i].k = j;
samplenum[i].colorvalue = RGB(255*3/(j+1)%255,255*14/(j+1)%255,255*21/(j+1)%255);
}
}
}
OnDraw(pDC);
CFont MyFont;
MyFont.CreateFont(30,0,0,0,400,FALSE,FALSE,0,
ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,DEFAULT_PITCH|FF_SWISS,"楷体_GB2312");
CFont* pOldFont=pDC->SelectObject(&MyFont);
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(RGB(255,0,255));
char number[80];
sprintf(number,"迭代次数:%d",iterativenum);
pDC->TextOut(600,20,number);
MyFont.DeleteObject();
//是否显示中心点
bshowcen = true;
Sleep(20);
///////////////////////////////////////////////////////////////
// 第三、四步:修正各聚类中心值并放置于oldprecen[i]及
// 判断iK个聚类中的每一聚类样本数是否小于iSetaN,否则iK-1,取消该样本子集
int sumnum[10] = {0,0,0,0,0,0,0,0,0,0};
float sumcencx[10] = {0,0,0,0,0,0,0,0,0,0};
float sumcency[10] = {0,0,0,0,0,0,0,0,0,0};
float L;
for(i = 0; i < iShuMu*iDianShu; i++)
{
for(k = 0; k < iK; k++)
{
if(samplenum[i].k == k)
{
sumcencx[k] = samplenum[i].cx + sumcencx[k];
sumcency[k] = samplenum[i].cy + sumcency[k];
sumnum[k]++;
}
}
}
for(k = 0; k < iK; k++)
{
samplecen[k].cx = sumcencx[k]/sumnum[k];
samplecen[k].cy = sumcency[k]/sumnum[k];
}
//赋值
for(i=0;i < iK;i++)
{
oldprecen[i] = samplecen[i];
}
//第三步:判断iK聚类中的样本数是否小于iSetaN,否则iK-1
SampleDot*tempnum;
tempnum = new SampleDot[16];
int oldclass[10] = {0,0,0,0,0,0,0,0,0,0};
int iNewK = -1;
//判断类内样本数是否小于iSetaN
for(k = 0; k < iK; k++)
{
if(sumnum[k] < iSetaN)//取消该样本子集
{
for(i = 0; i < iShuMu*iDianShu; i++)
{
if(samplenum[i].k == k)
{
samplenum[i].colorvalue = RGB(255,0,0);
samplenum[i].fseek = false;
}
}
}
else
iNewK++;
tempnum[iNewK] =oldprecen[k]; // tempnum[iNewK]用于放置新的聚类的中心点从0到 iNewK
oldclass[k]=iNewK;//oldclass[k]用于放置原本是第K类现在变成第iNewK类
}
for(i = 0; i < iShuMu*iDianShu; i++)//重新将样本点归类从从0到 iNewK进行归类
{
if(samplenum[i].fseek = true)//类内样本数大于iSetaN的聚类
{
samplenum[i].k = oldclass[k];//samplenum[i].k为NewK的值(NewK最大为iK)
}
}
//修正各聚类中心值(0到iK-1为新的聚类数)
iK=iNewK+1;
for(i=0;i < iK;i++)
{
oldprecen[i] =tempnum[i];// tempnum[i]用于放置新的聚类的中心点从0到 iNewK
}
//判断显示的中心点
for(i = 0; i < iK; i++)
{
samplecen[i] = oldprecen[i];
samplecen[i].fseek = true;
}
for(i = iK; i < iShuMu; i++)
{
samplecen[i].fseek = false;
}
//OnDraw(pDC);//会导致字体无法显示
////////////////////////////////////////////////////////////////
//第五步:计算各聚类域中样本离聚类中心的平均距离
float cenkdis[15];
float cenkavdis[15];
for(k = 0; k < iK; k++)
{
sumnum[k] = 0;
cenkdis[k] = 0;
}
for(i = 0;i < iShuMu * iDianShu;i++)
{
if(samplenum[i].fseek = true)
{for(k = 0;k < iK;k++)
{
if(samplenum[i].k == k)
{ olddis = sqrt((samplenum[i].cx - oldprecen[k].cx) * (samplenum[i].cx - oldprecen[k].cx)
+ (samplenum[i].cy - oldprecen[k].cy) * (samplenum[i].cy - oldprecen[k].cy));
cenkdis[k] = olddis + cenkdis[k];
sumnum[k]++;
}
}
}
}
for(k = 0;k < iK;k++)
{
cenkavdis[k]=cenkdis[k]/sumnum[k];
}
//////////////////////////////////////////////////////////////////////
//第六步:计算全部样本对相应聚类中心之间的平均距离
float cenavdis = 0;
int totalnum=0;
for(k = 0; k < iK; k++)
{
totalnum= sumnum[k] + totalnum ;
}
for(k = 0; k < iK; k++)
{
cenavdis = cenkdis[k] + cenavdis ;
}
cenavdis = cenavdis / totalnum;
//////////////////////////////////////////////////////////////////////
//第七步:判断下一步作分裂,合并及迭代运算等步骤
//判断迭代运算是否已达到规定值
if(iterativenum == iI)
{
fSetaC = 0;
goto step11;
}
//判断预测中心点数是否小于规定值的一半 //记录中心点数规定值
//int iknum = iK即iknum放置预期的聚类中心数目;
if(iK <= iknum/2)
goto step8;
//判断预测中心点数是否大于规定值的两倍
if(iterativenum%2==0 || iK >= 2 * iknum)
goto step11;
//////////////////////////////////////////////////////////////////////////
//第八步:计算每个聚类中样本距离的标准差向量(二维)
step8://分裂处理:
float totalx[15],totaly[15];//二维空间
float maxstand[15];
for(i = 0;i < iK;i++)
{
totalx[i] = 0.0;
totaly[i] = 0.0;
maxstand[i] = 0.0;
}
for(k = 0; k < iK; k++)
{
sumnum[k] = 0;
}
for(i = 0;i < iShuMu * iDianShu;i++)
{
if(samplenum[i].fseek = true)
{
totalx[samplenum[i].k]+=(samplenum[i].cx-samplecen[samplenum[i].k].cx)*(samplenum[i].cx-samplecen[samplenum[i].k].cx);
totaly[samplenum[i].k]+=(samplenum[i].cy-samplecen[samplenum[i].k].cy)*(samplenum[i].cy-samplecen[samplenum[i].k].cy);
sumnum[samplenum[i].k]++;
}//
}
////////////////////////////////////////////////////////////////////////
//第九步:求每个标准差向量中的最大值
for(i = 0;i < iK;i++)
{
totalx[i] = sqrt(totalx[i]/sumnum[i]);
totaly[i] = sqrt(totaly[i]/sumnum[i]);
if(totalx[i] >= totaly[i])
maxstand[i] = totalx[i];
else
maxstand[i] = totaly[i];
}
////////////////////////////////////////////////////////////////////////////
//第十步:分裂运算
for(i = 0;i < iK;i++)
{
if(maxstand[i] > fSetaS)
{
if(((cenkavdis[i] > cenavdis) && (sumnum[i] > 2 * (iSetaN + 1)))||(iK <= iknum/2))
{
samplecen[i].cx = samplecen[i].cx - 0.8 * maxstand[i];
//samplecen[i].cy = samplecen[i].cy - 0.8 * maxstand[i];
oldprecen[i] = samplecen[i];
samplecen[iK].cx = samplecen[iK].cx + 0.8 * maxstand[i];
//samplecen[iK].cy = samplecen[iK].cy + 0.8 * maxstand[i];
oldprecen[iK] = samplecen[iK];
samplecen[iK].fseek = true;
iK++;
goto step2;
}
}
}
////////////////////////////////////////////////////////////////////////////
//第十一步:计算各聚类中心距离
step11:
float cenredis[20][20];
for(i = 0;i <iK ;i++)//0到iK-1
{
for(j = i + 1;j < iK+1;j++)//i + 1到iK
{
cenredis[i][j] = (oldprecen[i].cx-oldprecen[j].cx)*(oldprecen[i].cx-oldprecen[j].cx)+(oldprecen[i].cy-oldprecen[j].cy)*(oldprecen[i].cy-oldprecen[j].cy);
}
}
////////////////////////////////////////////////////////////////////////////////
//第十二步和第十三步:比较类间距离,进行合并
int tempiK = iK;
for(i = 0;i < tempiK ;i++)
{
for(j = i + 1;j < tempiK+1;j++)
{
if(cenredis[i][j] < fSetaC)
{
samplecen[i].cx = (samplecen[i].cx * sumnum[i] + samplecen[j].cx * sumnum[j])/(sumnum[i] + sumnum[j]);
samplecen[i].cy = (samplecen[i].cy * sumnum[i] + samplecen[j].cy * sumnum[j])/(sumnum[i] + sumnum[j]);
oldprecen[i] = samplecen[i];
samplecen[j].fseek = false;
iK--;
goto step2;
}
}
}
////////////////////////////////////////////////////////////////////////////////////
//第十四步:判断是否迭代结束
//判断是否找到中心点
if(iterativenum < iI)
{
goto step2;
}
/* for(k = 0; k < iK; k++)
{
if(samplecen[k].cx == oldprecen[k].cx && samplecen[k].cy == oldprecen[k].cy)
goto endloop;
}
endloop:*/
delete [] oldprecen;
bshowcen = false;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -