📄 indatt.cpp
字号:
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "../RSet.h"
#include "indatt.h"
#include "stdio.h"
#include "stdlib.h"//function atoi();
#include "string.h"
#define MAX 10000
//#define max1 10000
/////////////////////
// IndAttRed class //
/////////////////////
IndAttRed::IndAttRed()
{
pFileName=NULL; //待处理的文件名
pIntTable=NULL; //原始表,为int类型,中间对象,转化为info表,最后处理用到
pInfo=NULL; //原始表,已转化为int,处理中主要对象,约简对象
cStyle=NULL; //数据集基本类型
pAttName=NULL; //属性名称(安列分)
pDataType=NULL; //数据类型(安列分)
struWCutRecord=NULL; //断点链表
pCoreCD=NULL; //C的D核
pmRedCD=NULL; //最小属性集合,也是所求结果
pnegCoreCD=NULL; //最小属性集合的补集
pPosCD=NULL; //Posc(D)
pDemSet=NULL; //pCoreCD的幂集
max2=MAX;
}
IndAttRed::~IndAttRed()
{
FreeContent();
}
////////////////////////////////////////////////////////
//the implementation of the public methods
/////////////////////////////////////////////////////////
bool IndAttRed::GetInfo(char* FileName)//get the privilege pInformation from the file given.
{ //从文件中得到数据,得到int型表
FILE* fp;
//return when fail to read the file
if((fp = fopen(FileName,"r")) == NULL)
{
AfxMessageBox("Can't open the file!");
return false;
}
cStyle= new char[20];
fscanf(fp,"Style:%s\n",cStyle);
fscanf(fp,"Stage:%d\n",&iStage);
fscanf(fp,"Condition attributes number:%d\n",&iConNum);
fscanf(fp,"Records number:%d\n",&iRecNum);
ipriRecNum=iRecNum;
SetAttName(fp,iConNum+1);
SetDataType(fp,iConNum+1);
SetIntegerTable(fp,iConNum+1,iRecNum);//fill the integertable
SetCutResult(fp);
fclose(fp);
return true;
}
bool IndAttRed::InitTable()//初始化决策表,得到int类型的表
{
int i,j;
if((pInfo=new int *[iRecNum])==0)
return false;
for (i=0;i<iRecNum;i++)
if((pInfo[i]=new int [iConNum+1])==0)
{
AfxMessageBox("内存不足!");
return false;
}
for (i=0;i<iRecNum;i++)
{
for (j=0;j<iConNum+1;j++)
{
pInfo[i][j]=pIntTable[i][j];
}
}
return true;
}
bool IndAttRed::DelOverlap()//删除重复的记录
{
int i,j,k,t; //循环变量
int ** pInfoset; //删除重复记录后的信息表
int new_iRecNum=0; //新信息表中的记录数
int sum=0; //统计属性值相同的个数
bool find=false;
int * same_rec;
if((same_rec=new int[iRecNum])==0)
{
AfxMessageBox("内存不足!");
return false;
}
int same_num=0;
//把重复记录编号存在same_rec中,same_num中为重复记录数目
for(i=0;i<iRecNum-1;i++)
for(j=i+1;j<iRecNum;j++)
{
//比较两条记录是否完全相等
for(k=0;k<iConNum+1;k++)
if(pInfo[i][k]==pInfo[j][k])
sum++;
else
break;
//表示完全相等
if(sum==(iConNum+1))
{
for(t=0;t<same_num;t++)
//如果记录中有i,说明第j条记录已存在same_rec中了
if(same_rec[t]==i)
{
find=true;
break;
}
if(find==false)
same_rec[same_num++]=j;//编号加入重复记录数组
}
find=false;
sum=0;
}
if(same_num>0)//如果有重复记录
{
//为新表分配空间
if((pInfoset=new int * [iRecNum-same_num])==0)
{
AfxMessageBox("内存不足!");
return false;
}
for(i=0;i<(iRecNum-same_num);i++)
{
if((pInfoset[i]=new int[iConNum+1])==0)
{
AfxMessageBox("内存不足!");
return false;
}
}
for(i=0;i<iRecNum;i++)
{
for(j=0;j<same_num;j++)
if(i==same_rec[j])
break;
else
sum++;
if(sum==same_num)//说明第i条记录不在same_rec中
{
for(j=0;j<iConNum+1;j++)
{//new_iRecNum为新信息表中的记录数 拷贝所有属性
pInfoset[new_iRecNum][j]=pInfo[i][j];
}
new_iRecNum++;
}
sum=0;
}
for(i=0;i<iRecNum;i++)
delete []pInfo[i];
delete []pInfo;
pInfo=pInfoset;//重新初始化
iRecNum-=same_num;//得到的不重复的新的记录数
}
delete []same_rec;
return true;
}
bool IndAttRed::SetIntegerTable(FILE* fp,int column, int row)
{
int i,j;
char* string=new char[MAX];
if((pIntTable = new int*[row])==0)
return false;
for(i = 0;i<row;i++)
{
if((pIntTable[i] = new int[column])==0)
return false;
}//end for
for(i=0;i<row;i++)
{
for(j=0;j<column;j++)
{
fscanf(fp,"%s",string);
if(strcmp(string,"-") == 0)
pIntTable[i][j] = -1;
else
pIntTable[i][j] = atoi(string);
}//end for
}//end for
delete []string;
return true;
}
bool IndAttRed::SetCutResult(FILE* fp)
{
int n;
int iColumn;
int iCuts;
struct WCutRecord* pHead = NULL;
struct WCutRecord* pEnd = NULL;
char* temp = new char[MAX];
if(fscanf(fp,"%s",temp) == -1)
{
delete[] temp;
return false;
}
if(strcmp(temp,"[Cuts]") != 0)
{
delete[] temp;
return false;
}
// bCuts = true;
while(fscanf(fp,"%d",&iColumn) != -1)
{
fscanf(fp,"%d",&iCuts);
pEnd = new WCutRecord;
if((pEnd->cpCut=new char*[iCuts])==0)
return false;
for(int i=0;i<iCuts;i++)
{
if((pEnd->cpCut[i] = new char[MAX])==0)
return false;
}//end for
pEnd->iColumn=iColumn;
pEnd->iCuts=iCuts;
pEnd->next=NULL;
for(i=0;i<iCuts;i++)
{
fscanf(fp,"%s",temp);//断点区间
fscanf(fp,"%d",&n);//断点号
strcpy(pEnd->cpCut[n],temp);//拷贝断点区间
}//end for
if(pHead == NULL)
{
struWCutRecord = pEnd;
pHead = pEnd;
}//end if
else
{
pHead->next = pEnd;
pHead = pEnd;
}//end else
}//end while
delete[] temp;
return true;
}
bool IndAttRed::SetAttName(FILE* fp, int count)
{
int i;
if((pAttName = new char*[count])==0)
return false;
for(i=0;i < count;i++)
{
if((pAttName[i]=new char[MAX])==0)
return false;
}//end for
for(i=0;i < count;i++)
fscanf(fp,"%s",pAttName[i]);
return true;
}
bool IndAttRed::SetDataType(FILE *fp, int count)
{
int i;
if((pDataType = new char*[count])==0)
return false;
for(i = 0;i < count;i++)
{
if((pDataType[i]=new char[MAX])==0)
return false;
}//end for
for(i = 0;i < count;i++)
fscanf(fp,"%s",pDataType[i]);
return true;
}
bool IndAttRed::SaveFile(char *pFileName)
{
int *a;
if((a=new int[iConNum])==0)
return false;
int i,j,t,k,m=0,n;
FILE* fp;
int iConNum1=pmRedCD->PosNum;
// if(nSelected == -1)
// return false;
if((fp = fopen(pFileName,"w")) == NULL)
{
AfxMessageBox("Can not open file for writing!");
return false;
}//end if
fprintf(fp,"Style:%s\n",cStyle);
fprintf(fp,"Stage:%d\n",3);//3 stands for 属性约简结果
fprintf(fp,"Condition attributes number:%d\n",iConNum1);
for(i = 0;i < iConNum;i++)
{
t=0;
for(k=0;k<pmRedCD->PosNum;k++)
{
if(pmRedCD->PosSet[k] == i)
{
t=1;
break;
}
}
if(t!=1)//删除了的属性,记录位置
a[m++]=i;
}
fprintf(fp,"The Number of Condition attributes deleted:%d\n",m);
fprintf(fp,"The position of Condition attributes deleted:");
if(m>0)
for(i=0;i<m;i++)
fprintf(fp," %d",a[i]);
fprintf(fp,"\n");
fprintf(fp,"Records number:%d\n",ipriRecNum);
for(i = 0;i < iConNum;i++)
{
t=0;
for(k=0;k<pmRedCD->PosNum;k++)
{
if(pmRedCD->PosSet[k] == i)
{
t=1;
break;
}
}
if(t==1)//是约简结果,输出
fprintf(fp,"%s ",pAttName[i]);
}
fprintf(fp,"%s ",pAttName[iConNum]);//决策的名字
fprintf(fp,"\n");
for(i = 0;i < iConNum;i++)
{
t=0;
for(k=0;k<pmRedCD->PosNum;k++)
{
if(pmRedCD->PosSet[k] == i)
{
t=1;
break;
}
}
if(t==1)//是约简结果,输出
fprintf(fp,"%s ",pDataType[i]);
}
fprintf(fp,"%s ",pDataType[iConNum]);//决策的数据类型
fprintf(fp,"\n");
for(i=0;i<ipriRecNum;i++)//行
{
for(j=0;j<iConNum;j++)//列
{
t=0;
for(k=0;k<pmRedCD->PosNum;k++)
{
if(pmRedCD->PosSet[k] == j)
{
t=1;
break;
}
}
if(t==1)//是核,打印
fprintf(fp,"%d ",pIntTable[i][j]);
// else//or press '-'
//fprintf(fp,"%c ",'-');
}
fprintf(fp,"%d ",pIntTable[i][iConNum]);//决策属性单独处理
fprintf(fp,"\n");
}
if(struWCutRecord == NULL)//没有断点
{
fclose(fp);
return true;
}
struct WCutRecord* temp = struWCutRecord;
n=0;
fprintf(fp,"[Cuts]\n");
while(temp != NULL)
{
bool flag=true;
for(i=0;i<m;i++)
if (a[i]==temp->iColumn)
{
flag=false;
n++;//表示中间空缺的属性数目
break;
}
if(flag)
{
fprintf(fp,"%d\n",(temp->iColumn)-n);
fprintf(fp,"%d\n",temp->iCuts);
for(i = 0;i < temp->iCuts;i++)
{
fprintf(fp,"%s ",temp->cpCut[i]);
fprintf(fp,"%d\n",i);
}
}
temp = temp->next;
}
fclose(fp);
delete []a;
return true;
}
//首先求U|ind(X),再求U|D,然后求Pos(X)D
bool IndAttRed::PosXD(int XNum,int* XSet,PosD* &PosXD)
{//PosXD->PosNum表示正域中元素的个数
if(XNum==0)
{
PosXD->PosNum=0;
return true;
}
PosXD->PosNum=0;
int iClassNumD=0;//决策D的分类数目
int DNum=1;
int *DSet=new int[1];
DSet[0]=iConNum;//决策属性位置。表示用决策来分类
int **UindD;
if((UindD=new int*[iRecNum])==0)//记录数,约简对象
return false;
for(int j=0;j<iRecNum;j++)
if((UindD[j]=new int[iRecNum+1])==0)
return false;
//call UindX()//求U|D,结果放在iClassNumD,UindD 中
UindX(DNum,DSet,iClassNumD,UindD);
delete []DSet;
int iClassNumX=0;
int **pUindX;
if((pUindX=new int*[iRecNum])==0)
return false;
for(j=0;j<iRecNum;j++)
if((pUindX[j]=new int[iRecNum+1])==0)
return false;
//call UindX() //求U|ind(X),结果放在iClassNumX,pUindX中
UindX(XNum,XSet,iClassNumX,pUindX);
//求pos(x)D
//就是包含在u|d中的uindX的并集
//简化算法,如果uindx的某一类的元素全在U\D的同一类中,那么就是
for(int i=0;i<iClassNumX;i++)//对uindx中的每一类
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -