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

📄 200532590150view.cpp

📁 实现了二维数据的K均值算法以及ISODATA分类算法
💻 CPP
字号:
// 200532590150View.cpp : implementation of the CMy200532590150View class
//

#include "stdafx.h"
#include "200532590150.h"

#include "200532590150Doc.h"
#include "200532590150View.h"
#include "KAverageDialog.h"
#include "IsodataDialog.h"
#include "ParaDialog.h"
#include "math.h"
#include "MainFrm.h"
#include "ChildFrm.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CMy200532590150View

IMPLEMENT_DYNCREATE(CMy200532590150View, CView)

BEGIN_MESSAGE_MAP(CMy200532590150View, CView)
	//{{AFX_MSG_MAP(CMy200532590150View)
	ON_COMMAND(ID_ASSEMBLE_KAVE, OnAssembleKave)
	ON_COMMAND(ID_ASSEMBLE_ISO, OnAssembleIso)
	//}}AFX_MSG_MAP
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMy200532590150View construction/destruction

CMy200532590150View::CMy200532590150View()
{
	// TODO: add construction code here

}

CMy200532590150View::~CMy200532590150View()
{
}

BOOL CMy200532590150View::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CMy200532590150View drawing

void CMy200532590150View::OnDraw(CDC* pDC)
{
	CMy200532590150Doc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here

	//K均值算法结果绘图
	if(flag==1)
	{
		//画坐标轴及刻度等
		pDC->MoveTo(250,20);
		pDC->LineTo(250,380);
		pDC->LineTo(615,380);
		pDC->MoveTo(610,375);
		pDC->LineTo(615,380);
		pDC->LineTo(610,385);
		pDC->TextOut(615,390,"x1");
		pDC->MoveTo(245,25);
		pDC->LineTo(250,20);
		pDC->LineTo(255,25);
		pDC->TextOut(225,5,"x2");
		pDC->TextOut(245,390,"0");
		for(int i=1;i<8;i++)
		{
			CString str;
			str.Format("%d",i);
			pDC->TextOut(245+i*50,390,str);
			pDC->MoveTo(250+i*50,380);
			pDC->LineTo(250+i*50,375);
			pDC->TextOut(230,375-i*50,str);
			pDC->MoveTo(250,380-i*50);
			pDC->LineTo(255,380-i*50);
		}

		CClientDC DC(this);
		OnPrepareDC(&DC);

		//画聚类结果
		//将类群1的点用蓝色表示
		for(i=0;i<num[0];i++)
			for(int j1=-1;j1<2;j1++)
				for(int j2=-1;j2<2;j2++)
					SetPixel(DC,(int)(250+y1[i][0]*50+j1),(int)(380-y1[i][1]*50-j2),RGB(0,0,255));
		//将类群2的点用绿色表示
		for(i=0;i<num[1];i++)
			for(int j1=-1;j1<2;j1++)
				for(int j2=-1;j2<2;j2++)
		        	SetPixel(DC,(int)(250+y2[i][0]*50+j1),(int)(380-y2[i][1]*50-j2),RGB(0,255,0));
		//将类群3的点用红色表示
		for(i=0;i<num[2];i++)
			for(int j1=-1;j1<2;j1++)
				for(int j2=-1;j2<2;j2++)
			        SetPixel(DC,(int)(250+y3[i][0]*50+j1),(int)(380-y3[i][1]*50-j2),RGB(255,0,0));
		//将聚类中心用十字叉丝表示
		for(i=0;i<3;i++)
		{
			pDC->MoveTo((int)(250+z[i][0]*50-5),(int)(380-z[i][1]*50));
			pDC->LineTo((int)(250+z[i][0]*50+5),(int)(380-z[i][1]*50));
			pDC->MoveTo((int)(250+z[i][0]*50),(int)(380-z[i][1]*50-5));
			pDC->LineTo((int)(250+z[i][0]*50),(int)(380-z[i][1]*50+5));
		}
		//图表说明
		pDC->MoveTo(650,40);
		pDC->LineTo(660,40);
		pDC->MoveTo(655,35);
		pDC->LineTo(655,45);
		pDC->TextOut(670,33,"聚类中心");
		for(int j1=-1;j1<2;j1++)
				for(int j2=-1;j2<2;j2++)
			        SetPixel(DC,655+j1,60-j2,RGB(0,0,0));
        pDC->TextOut(670,53,"样本(不同颜色表示类别)");
	}

	//ISODATA算法结果绘图
	else if(flag==2)
	{
		//画坐标轴及刻度等
		pDC->MoveTo(250,20);
		pDC->LineTo(250,380);
		pDC->LineTo(615,380);
		pDC->MoveTo(610,375);
		pDC->LineTo(615,380);
		pDC->LineTo(610,385);
		pDC->TextOut(615,390,"x1");
		pDC->MoveTo(245,25);
		pDC->LineTo(250,20);
		pDC->LineTo(255,25);
		pDC->TextOut(225,5,"x2");
		pDC->TextOut(245,390,"0");
		for(int i=1;i<8;i++)
		{
			CString str;
			str.Format("%d",i);
			pDC->TextOut(245+i*50,390,str);
			pDC->MoveTo(250+i*50,380);
			pDC->LineTo(250+i*50,375);
			pDC->TextOut(230,375-i*50,str);
			pDC->MoveTo(250,380-i*50);
			pDC->LineTo(255,380-i*50);
		}

		CClientDC DC(this);
		OnPrepareDC(&DC);
		
		//画分类结果
		int d=255/C;
		for(i=0;i<count;i++)
		{
			for(int j=0;j<C;j++)
			{
			    //将各类样本用不同颜色表示
			    if((int)(pDoc->x[i].type)==j)
				{
				    for(int j1=-1;j1<2;j1++)
				        for(int j2=-1;j2<2;j2++)
					         SetPixel(DC,(int)(250+(pDoc->x[i].x1)*50+j1),
						     (int)(380-(pDoc->x[i].x2)*50-j2),RGB(j*d,
						      255-d,(255-j*d)));
				}
				else
					continue;
			}
		}
		//将聚类中心用十字叉丝表示
		for(i=0;i<C;i++)
		{
			pDC->MoveTo((int)(250+z[i][0]*50-5),(int)(380-z[i][1]*50));
			pDC->LineTo((int)(250+z[i][0]*50+5),(int)(380-z[i][1]*50));
			pDC->MoveTo((int)(250+z[i][0]*50),(int)(380-z[i][1]*50-5));
			pDC->LineTo((int)(250+z[i][0]*50),(int)(380-z[i][1]*50+5));
		}
		//图表说明
		pDC->MoveTo(650,40);
		pDC->LineTo(660,40);
		pDC->MoveTo(655,35);
		pDC->LineTo(655,45);
		pDC->TextOut(670,33,"聚类中心");
		for(int j1=-1;j1<2;j1++)
				for(int j2=-1;j2<2;j2++)
			        SetPixel(DC,655+j1,60-j2,RGB(0,0,0));
        pDC->TextOut(670,53,"样本(不同颜色表示类别)");
	}
	else 
		;
}

/////////////////////////////////////////////////////////////////////////////
// CMy200532590150View printing

BOOL CMy200532590150View::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void CMy200532590150View::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printing
}

void CMy200532590150View::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}

/////////////////////////////////////////////////////////////////////////////
// CMy200532590150View diagnostics

#ifdef _DEBUG
void CMy200532590150View::AssertValid() const
{
	CView::AssertValid();
}

void CMy200532590150View::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CMy200532590150Doc* CMy200532590150View::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMy200532590150Doc)));
	return (CMy200532590150Doc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CMy200532590150View message handlers

void CMy200532590150View::OnAssembleKave() 
{
	// TODO: Add your command handler code here
	CKAverageDialog dlg;

	int count;//样本个数
	double x1[100]={0},x2[100]={0};//特征x1及特征x2
	double z1[3][2]={0};//新聚类中心
	int i,j;//循环变量
	double temp[6];//中间变量

	//全局变量归零
	for(i=0;i<3;i++)
	{
		z[i][0]=0;
        z[i][1]=0;
		num[i]=0;
	}
	for(i=0;i<100;i++)
		for(j=0;j<2;j++)
		{
			y1[i][j]=0;
			y2[i][j]=0;
			y3[i][j]=0;
		}
	flag=count=0;

	//画图标记
	if(dlg.DoModal()==IDOK)
		flag=1;


	//将对话框中的参数赋予相应变量
	count=dlg.count;
	for(i=0;i<count;i++)
	{
		x1[i]=dlg.x1[i];
		x2[i]=dlg.x2[i];
	}
	z[0][0]=dlg.m_z1;
	z[0][1]=dlg.m_z2;
	z[1][0]=dlg.m_z3;
	z[1][1]=dlg.m_z4;
	z[2][0]=dlg.m_z5;
	z[2][1]=dlg.m_z6;

	delete dlg;

	//函数声明
	void classify(double [],double [],double [][2],int [],
		   double [][2],double [][2],double [][2],int);//依据聚类中心分类函数
    void center(double [][2],double [][2],double [][2],double [3][2],int []);//计算聚类中心函数
 
	while(temp[0]!=0&&temp[1]!=0&&temp[2]!=0&&temp[3]!=0&&temp[4]!=0&&temp[5]!=0)//判断最近两次迭代结果的聚类中心是否一致
	{
		//调用函数进行聚类
		classify(x1,x2,z,num,y1,y2,y3,count);
		//调用函数计算新的聚类中心
        center(y1,y2,y3,z1,num);
        //计算新的聚类中心与上一次的聚类中心的差值
	    temp[0]=z1[0][0]-z[0][0];
	    temp[1]=z1[0][1]-z[0][1];
	    temp[2]=z1[1][0]-z[1][0];
	    temp[3]=z1[1][1]-z[1][1];
	    temp[4]=z1[2][0]-z[2][0];
	    temp[5]=z1[2][1]-z[2][1];
        //将新的聚类中心存放于初始聚类中心数组中
		for(i=0;i<3;i++)
			for(j=0;j<2;j++)
			{
				z[i][j]=z1[i][j];
				z1[i][j]=0;
			}
	}

	Invalidate();
}

void CMy200532590150View::OnAssembleIso() 
{
	// TODO: Add your command handler code here
	CIsodataDialog dlg;
	CParaDialog paradlg;

	CMy200532590150Doc *pDoc = GetDocument();

	int K,qn,L,I;//所要求的聚类中心数、一个类别至少应有的样本数目、
	              //每次迭代可归并的最多类别对数、允许迭代的最多次数
	double qs,qc;//一个类别样本标准差阈值、聚类中心间距离的阈值
	double d[20],D,dc[20][20];//各聚类中的样本到中心的平均距离、
	                      //所有样本到各中心的平均距离、两样本中心间的距离
	double Q[20][2],Qmax[20];//各类群标准差向量、各标准差向量的最大分量
	int i,k=0,m,n;//循环变量及中间变量
	int flag1;//标记进入第几步
	double per[20],a;//各类样本占总样本数的百分比	

	//全局变量归零
	for(i=0;i<100;i++)
	{
		pDoc->x[i].x1=0;
		pDoc->x[i].x2=0;
		pDoc->x[i].type=0;
	}
	for(i=0;i<20;i++)
	{
		z[i][0]=0;
		z[i][1]=0;
		num[i]=0;
	}
	C=count=flag=0;
	pDoc->flagpara=0;

	//画图标记
	if(dlg.DoModal()==IDOK)
		flag=2;


	//将对话框中的参数赋予相应变量
	count=dlg.count;
	for(i=0;i<count;i++)
	{
		pDoc->x[i].x1 =dlg.x1[i];
		pDoc->x[i].x2 =dlg.x2[i];
	}
	
	//第一步:确定初始聚类样本
	C=2;
	//随机选择两个输入样本
	m=rand()%(count-1);
	z[0][0]=pDoc->x[m].x1;
	z[0][1]=pDoc->x[m].x2;
    pDoc->x[m].type=0;
	n=rand()%(count-1);
	while(n==m)
		n=rand()%(count-1);
	z[1][0]=pDoc->x[n].x1;
	z[1][1]=pDoc->x[n].x2;
    pDoc->x[m].type=1;


	//第二步:确定六个参数
	K=dlg.m_7;
	qn=dlg.m_8;
	qs=dlg.m_9;
	qc=dlg.m_10;
	L=dlg.m_11;
	I=dlg.m_12;

	delete dlg;

	while(k<=I)
	{
		k++;
		//第二步:修改参数
		if(pDoc->flagpara==1)
		{
			paradlg.m_7=K;
			paradlg.m_8=qn;
			paradlg.m_9=qs;
			paradlg.m_10=qc;
			paradlg.m_11=L;
			paradlg.m_12=I;

			if(paradlg.DoModal()==IDOK)
			{
            	K=paradlg.m_7;
	            qn=paradlg.m_8;
	            qs=paradlg.m_9;
	            qc=paradlg.m_10;
	            L=paradlg.m_11;
	            I=paradlg.m_12;
			}
			delete paradlg;
			pDoc->flagpara=0;
		} 
		//第三步:按最小距离分类
		pDoc->classify1(z,num,count,C);
		//第四步:若样本数目不合要求则取消该子集
		for(i=0;i<C;i++)
			if(num[i]<qn)
			C=pDoc->cancelsubset(z,num,count,C,i);
		//第五步:修正聚类中心值
        pDoc->center1(z,num,count,C);
		//第六及第七步:计算各类群样本距中心的平均距离及所有样本距相应中心的距离的平均值
		D=pDoc->distance(z,num,count,C,d);
		//第八步
		//若迭代次数达到I次
        if(k==I)
		{
			qc=0;//置qc为零
			flag1=0;//转入第十二步
		}
		//若C<=K/2
		else if(C<=K/2)
			flag1=1;//转入第九步
		else if(C>=2*K)
			flag1=0;//转入第十二步
		else if(C<2*K&&C>K/2)
		{
			if(k%2==1)
				flag1=1;//迭代次数为奇数则转第九步
            else if(k%2==0)
				flag1=0;//迭代次数为偶数则转第十二步
		}
		if(flag1==1)
		{
			//第九及第十步:计算各类样本与聚类中心的距离的标准差向量及最大分量
			pDoc->biaozhuncha(z,num,count,C,d,Q,Qmax);
			//第十一步:分裂
			for(i=0;i<C;i++)
			{
				if(Qmax[i]>qs)
				{
					if((d[i]>D&&num[i]>2*(qn+1))||C<=K/2)
						C=pDoc->split(Qmax,Q,z,C,i,dc,num,count,qc);
					else 
						;
				}
				else
					continue;
			}
		}
		else if(flag1==0)
		{
			//第十二步:计算每两个聚类中心间的距离
			pDoc->centerD(z,dc,C);
			//第十三及十四步:将小于qc的距离值按从小到大的顺序组成一个集合,然后逐一合并
            C=pDoc->combine(dc,C,qc,L,count,z,num);
		}
		//计算各类样本占总样本的百分比
		a=0;
		for(i=0;i<C;i++)
		{
			per[i]=num[i]*1.0/count;
			if(per[i]<0.15)
				a++;
		}
		//第十五步:判断是否需要修改参数
		if((C<K&&k*1.0/I>0.6)||a/C>0.4)
			pDoc->flagpara=1;
	}


	Invalidate();


}

⌨️ 快捷键说明

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