【C】【吐血整理】你们要的C语言实例大全-综合应用篇
目录
实例94 用C语言实现遗传算法
ga.c
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#define SUM 20 //总共的染色体数量
#define MAXloop 1200 //最大循环次数
#define error 0.01 //若两次最优值之差小于此数则认为结果没有改变
#define crossp 0.7 //交叉概率
#define mp 0.04 //变异概率
struct gen //定义染色体结构
{
int info;
float suitability;
};
struct gen gen_group[SUM];//定义一个含有20个染色体的组
struct gen gen_new[SUM];
struct gen gen_result; //记录最优的染色体
int result_unchange_time; //记录在error前提下最优值为改变的循环次数
struct log //形成链表,记录每次循环所产生的最优的适应度
{
float suitability;
struct log *next;
}llog,*head,*end;
int log_num; //链表长度
void initiate();
void evaluation(int flag);
void cross();
void selection();
int record();
void mutation();
void showresult(int);
int randsign(float p);
int randbit(int i,int j);
int randnum();
int convertionD2B(float x);
float convertionB2D(int x);
int createmask(int a);
void main()
{
int i,flag;
flag=0;
initiate();
evaluation( 0 );
for( i = 0 ; i < MAXloop ; i++ )
{
cross();
evaluation( 1 );
selection();
if( record() == 1 )
{
flag = 1;
break;
}
mutation();
}
showresult( flag );
}
void initiate()
{
int i , stime;
long ltime;
ltime=time(NULL);
stime=(unsigned)ltime/2;
srand(stime);
for( i = 0 ; i < SUM ; i++ )
{
gen_group[i].info = randnum();
}
gen_result.suitability=1000;
result_unchange_time=0;
head=end=(struct log *)malloc(sizeof(llog));
if(head==NULL)
{
printf("\n内存不够!\n");
exit(0);
}
end->next = NULL;
log_num = 1;
}
void evaluation(int flag)
{
int i,j;
struct gen *genp;
int gentinfo;
float gentsuitability;
float x;
if( flag == 0 )
genp = gen_group;
else genp = gen_new;
for(i = 0 ; i < SUM ; i++)//计算各染色体对应的表达式值
{
x = convertionB2D( genp[i].info );
genp[i].suitability = x*(x*(x*(x*(x*(x-10)-26)+344)+193)-1846)-1680;
}
for(i = 0 ; i < SUM - 1 ; i++)//按表达式的值进行排序,
{
for(j = i + 1 ; j < SUM ; j++)
{
if( genp[i].suitability > genp[j].suitability )
{
gentinfo = genp[i].info;
genp[i].info = genp[j].info;
genp[j].info = gentinfo;
gentsuitability = genp[i].suitability;
genp[i].suitability = genp[j].suitability;
genp[j].suitability = gentsuitability;
}
}
}
}
void cross()
{
int i , j , k ;
int mask1 , mask2;
int a[SUM];
for(i = 0 ; i < SUM ; i++) a[i] = 0;
k = 0;
for(i = 0 ; i < SUM ; i++)
{
if( a[i] == 0)
{
for( ; ; )//随机找到一组未进行过交叉的染色体与a[i]交叉
{
j = randbit(i + 1 , SUM - 1);
if( a[j] == 0) break;
}
if(randsign(crossp) == 1)
{
mask1 = createmask(randbit(0 , 14));
mask2 = ~mask1;
gen_new[k].info = (gen_group[i].info) & mask1 + (gen_group[j].info) & mask2;
gen_new[k+1].info=(gen_group[i].info) & mask2 + (gen_group[j].info) & mask1;
k = k + 2;
}
else
{
gen_new[k].info=gen_group[i].info;
gen_new[k+1].info=gen_group[j].info;
k=k+2;
}
a[i] = a[j] = 1;
}
}
}
void selection()
{
int i , j , k;
j = 0;
i = SUM/2-1;
if(gen_group[i].suitability < gen_new[i].suitability)
{
for(j = 1 ; j < SUM / 2 ; j++)
{
if(gen_group[i+j].suitability > gen_new[i-j].suitability)
break;
}
}
else
if(gen_group[i].suitability>gen_new[i].suitability)
{
for(j=-1;j>-SUM/2;j--)
{
if(gen_group[i+j].suitability<=gen_new[i-j].suitability)
break;
}
}
for(k=j;k<SUM/2+1;k++)
{
gen_group[i+k].info = gen_new[i-k].info;
gen_group[i+k].suitability = gen_new[i-k].suitability;
}
}
int record()
{
float x;
struct log *r;
r=(struct log *)malloc(sizeof(llog));
if(r==NULL)
{
printf("\n内存不够!\n");
exit(0);
}
r->next = NULL;
end->suitability = gen_group[0].suitability;
end->next = r;
end = r;
log_num++;
x = gen_result.suitability - gen_group[0].suitability;
if(x < 0)x = -x;
if(x < error)
{
result_unchange_time++;
if(result_unchange_time >= 20)return 1;
}
else
{
gen_result.info = gen_group[0].info;
gen_result.suitability = gen_group[0].suitability;
result_unchange_time=0;
}
return 0;
}
void mutation()
{
int i , j , m;
float x;
float gmp;
int gentinfo;
float gentsuitability;
gmp = 1 - pow(1 - mp , 11);//在基因变异概率为mp时整条染色体的变异概率
for(i = 0 ; i < SUM ; i++)
{
if(randsign(gmp) == 1)
{
j = randbit(0 , 14);
m = 1 << j;
gen_group[i].info = gen_group[i].info^m;
x = convertionB2D(gen_group[i].info);
gen_group[i].suitability = x*(x*(x*(x*(x*(x-10)-26)+344)+193)-1846)-1680;
}
}
for(i = 0 ; i < SUM - 1 ; i++)
{
for(j = i + 1 ; j < SUM ; j++)
{
if(gen_group[i].suitability > gen_group[j].suitability)
{
gentinfo = gen_group[i].info;
gen_group[i].info = gen_group[j].info;
gen_group[j].info = gentinfo;
gentsuitability = gen_group[i].suitability;
gen_group[i].suitability = gen_group[j].suitability;
gen_group[j].suitability = gentsuitability;
}
}
}
}
void showresult(int flag)//显示搜索结果并释放内存
{
int i , j;
struct log *logprint,*logfree;
FILE *logf;
if(flag == 0)
printf("已到最大搜索次数,搜索失败!");
else
{
printf("当取值%f时表达式达到最小值为%f\n",convertionB2D(gen_result.info),gen_result.suitability);
printf("收敛过程记录于文件log.txt");
if((logf = fopen("log.txt" , "w+")) == NULL)
{
printf("Cannot create/open file");
exit(1);
}
logprint=head;
for(i = 0 ; i < log_num ; i = i + 5)//对收敛过程进行显示
{
for(j = 0 ; (j < 5) & ((i + j) < log_num-1) ; j++)
{
fprintf(logf , "%20f" , logprint->suitability);
logprint=logprint->next;
}
fprintf(logf,"\n\n");
}
}
for(i = 0 ; i< log_num ; i++)//释放内存
{
logfree=head;
head=head->next;
free(logfree);
fclose(logf);
}
getchar();
}
int randsign(float p)//按概率p返回1
{
if(rand() > (p * 32768))
return 0;
else return 1;
}
int randbit(int i, int j)//产生在i与j之间的一个随机数
{
int a , l;
l = j - i + 1;
a = i + rand() * l / 32768;
return a;
}
int randnum()
{
int x;
x = rand() / 2;
return x;
}
float convertionB2D(int x)
{
float y;
y = x;
y = (y - 8192) / 1000;
return y;
}
int convertionD2B(float x)
{
int g;
g = (x * 1000) + 8192;
return g;
}
int createmask(int a)
{
int mask;
mask=(1 << (a + 1)) - 1;
return mask;
}
实例95 人工神经网络的C语言实现
BP.C
#include "math.h"
#include "time.h"
#include "stdio.h"
#include "stdlib.h"
#define Ni 1
#define Nm 4
#define No 1
#define L 100
#define Enom 0.02
#define loopmax 100000
#define e 2.71828
double E;
double a,u,n;
double W1[Ni][Nm],D1[Ni][Nm],W2[Nm][No],D2[Nm][No];
double D22[Nm][No],D11[Ni][No];
double a1[Ni][Nm],a2[Nm][No];
double Pi[L][Ni],Pm[L][Nm],Po[L][No],T[L][No];
double Xm[L][Nm],Xo[L][No];
double Qm[L][Nm],Qo[L][No];
void proceed();
void proceedR();
void forQ();
void amend();
void initiate();
double newa(double a,double D);
double cal(double d);
double vcal(double d);
main()
{
long int i;
int flag;
char choice;
for(;;)
{
flag=0;
initiate();
for(i=0;;i++)
{
proceed();
if( E < Enom )
{
flag=1;
break;
}
if( i >= loopmax)
{
flag = -1;
break;
}
if(i%2500==0)
printf("第%10d轮误差:%20f,学习速率:%10f\n",i,E,a1[0][0]);
forQ();
amend();
}
if(flag>0)proceedR();
else printf("训练失败!\n");
for(;;)
{
choice=getchar();
printf("是否继续?(Y/N)\n");
choice=getchar();
choice=toupper(choice);
if(choice=='Y')break;
if(choice=='N')exit(0);
}
}
}
void initiate()
{
int i,j;
int random;
double x;
double step;
int stime;
long ltime;
ltime=time(NULL);
stime=(unsigned)ltime/2;
srand(stime);
a=0.02;
u=1;
n=1;
printf("本程序将用BP神经网络拟合函数:Y=sin(X)\n\n");
for( i=0; i<Nm; i++)
{
for( j=0; j<Ni; j++)
{
random=rand()%100-50;
x=random;
x=x/100;
W1[j][i]=x;
D11[j][i]=0;
D1[j][i]=0;
a1[j][i]=0.01;
}
for( j=0; j<No; j++)
{
random=rand()%100-50;
x=random;
x=x/100;
W2[i][j]=x;
D22[i][j]=0;
D2[i][j]=0;
a2[i][j]=0.01;
}
}
step=1.0/L;
for(i=0;i<L;i++)
{
x=i;
Pi[i][0]=x*step;
T[i][0]=sin(Pi[i][0]);
}
printf("初始化成功!\n\n下面将对神经网络进行训练请稍候。\n");
}
void proceed()
{
int i, j, k;
E=0 ;
for( i=0; i<L; i++ )
{
for( j=0; j<Nm; j++ )
{
Pm[i][j] = 0;
for( k=0; k<Ni; k++ )
{
Pm[i][j] = Pi[i][k] * W1[k][j] + Pm[i][j];
}
Xm[i][j] = cal( Pm[i][j] );
}
for( j=0; j<No; j++)
{
Po[i][j] = 0;
for( k=0; k<Nm; k++)
{
Po[i][j] = Xm[i][k] * W2[k][j] + Po[i][j];
}
Xo[i][j] = cal( Po[i][j] );
E = E + ( Xo[i][j] - T[i][j] ) * ( Xo[i][j] - T[i][j] ) / 2;
}
}
}
void forQ()
{
int i,j,k;
for( i=0; i<L; i++ )
{
for( j=0; j<No; j++)
{
Qo[i][j] = ( T[i][j] - Xo[i][j] )* vcal( Xo[i][j] );
}
for(j=0; j<Nm; j++)
{
Qm[i][j]=0;
for( k=0; k<No; k++)
{
Qm[i][j] = Qo[i][k] * W2[j][k] + Qm[i][j];
}
Qm[i][j] = Qm[i][j] * vcal( Xm[i][j] );
}
}
}
void amend()
{
int i,j,k;
double D;
for( i=0; i<Nm; i++)
{
for( j=0; j<Ni; j++)
{
D1[j][i]=0;
}
for( j=0; j<No; j++)
{
D2[i][j]=0;
}
}
for( i=0; i<Ni; i++)
{
for( j=0; j<Nm; j++)
{
for( k=0; k<L; k++)
{
D1[i][j] = Qm[k][j] * Pi[k][i] + D1[i][j];
}
D = D1[i][j] * D11[i][j] ;//为D11付初值
a1[i][j] = newa( a1[i][j] , D ); // a 付初值
W1[i][j] = W1[i][j] + a1[i][j] * ( n * D1[i][j] + ( 1 - n ) * D11[i][j] );
D11[i][j] = D1[i][j];
}
}
for( i=0; i<Nm; i++)
{
for( j=0; j<No; j++)
{
for( k=0; k<L; k++)
{
D2[i][j] = Qo[k][j] * Xm[k][i] + D2[i][j];
}
D = D2[i][j] * D22[i][j] ;//为D11付初值
a2[i][j] = newa( a2[i][j] , D );
W2[i][j] = W2[i][j] + a2[i][j] * ( n * D2[i][j] + ( 1 - n ) * D22[i][j] );
D22[i][j] = D2[i][j];
}
}
}
void proceedR()
{
int i, j;
float x;
double input,output;
char choice;
for(;;)
{
for(;;)
{
printf("在此输入需要计算的值(0,1):\n");
scanf("%f",&x);
input=(double)x;
if((input>=0)&(input<=1))break;
printf("注意输入值应介于0、1之间!\n");
for(;;)
{
choice=getchar();
printf("是否继续?(Y/N)\n");
choice=getchar();
choice=toupper(choice);
if(choice=='Y')break;
if(choice=='N')exit(0);
}
}
for(i=0;i<Nm;i++)
{
Pm[0][i]=0;
for( j=0; j<Ni; j++ )
{
Pm[0][i] = input* W1[j][i]+Pm[0][i] ;
}
Xm[0][i] = cal( Pm[0][i] );
}
for( i=0; i<No; i++)
{
Po[0][i] = 0;
for( j=0; j<Nm; j++)
{
Po[0][i] = Xm[0][j] * W2[j][i]+Po[0][i];
}
}
output=cal( Po[0][0] );
printf("输入值为%20f对应的结果为%f\n",input,output);
printf("输入值为%20f对应的正常结果为%f\n",input,sin(input));
for(;;)
{
choice=getchar();
printf("是否继续?(Y/N)\n");
choice=getchar();
choice=toupper(choice);
if(choice=='Y')break;
if(choice=='N')exit(0);
}
}
}
double newa(double a, double D)
{
if( D > 0 )
{
{
if(a<=0.04)
a = a * 2;
else a=0.08;
}
}
else
if ( D < 0)
{
if(a>=0.02)
{
a = a / 2;
}
else a=0.01;
}
return a;
}
double cal(double d)
{
d = - (d * u); // chushihua
d = exp( d );
d = 1 / ( 1 + d );
return d;
}
double vcal(double d)
{
return u * d * ( 1 - d );
}
trust100@ubuntu:~/test/clanguage$ ./a.out
本程序将用BP神经网络拟合函数:Y=sin(X)
初始化成功!
下面将对神经网络进行训练请稍候。
第 0轮误差: 3.182817,学习速率: 0.010000
第 2500轮误差: 3.182817,学习速率: 0.010000
第 5000轮误差: 3.182817,学习速率: 0.010000
第 7500轮误差: 3.182817,学习速率: 0.010000
第 10000轮误差: 3.182817,学习速率: 0.010000
第 12500轮误差: 3.182817,学习速率: 0.010000
第 15000轮误差: 3.182817,学习速率: 0.010000
第 17500轮误差: 3.182817,学习速率: 0.010000
第 20000轮误差: 3.182817,学习速率: 0.010000
第 22500轮误差: 3.182817,学习速率: 0.010000
第 25000轮误差: 3.182817,学习速率: 0.010000
第 27500轮误差: 3.182817,学习速率: 0.010000
第 30000轮误差: 3.182817,学习速率: 0.010000
第 32500轮误差: 3.182817,学习速率: 0.010000
第 35000轮误差: 3.182817,学习速率: 0.010000
第 37500轮误差: 3.182817,学习速率: 0.010000
第 40000轮误差: 3.182817,学习速率: 0.010000
第 42500轮误差: 3.182817,学习速率: 0.010000
第 45000轮误差: 3.182817,学习速率: 0.010000
第 47500轮误差: 3.182817,学习速率: 0.010000
第 50000轮误差: 3.182817,学习速率: 0.010000
第 52500轮误差: 3.182817,学习速率: 0.010000
第 55000轮误差: 3.182817,学习速率: 0.010000
第 57500轮误差: 3.182817,学习速率: 0.010000
第 60000轮误差: 3.182817,学习速率: 0.010000
第 62500轮误差: 3.182817,学习速率: 0.010000
第 65000轮误差: 3.182817,学习速率: 0.010000
第 67500轮误差: 3.182817,学习速率: 0.010000
第 70000轮误差: 3.182817,学习速率: 0.010000
第 72500轮误差: 3.182817,学习速率: 0.010000
第 75000轮误差: 3.182817,学习速率: 0.010000
第 77500轮误差: 3.182817,学习速率: 0.010000
第 80000轮误差: 3.182817,学习速率: 0.010000
第 82500轮误差: 3.182817,学习速率: 0.010000
第 85000轮误差: 3.182817,学习速率: 0.010000
第 87500轮误差: 3.182817,学习速率: 0.010000
第 90000轮误差: 3.182817,学习速率: 0.010000
第 92500轮误差: 3.182817,学习速率: 0.010000
第 95000轮误差: 3.182817,学习速率: 0.010000
第 97500轮误差: 3.182817,学习速率: 0.010000
训练失败!
实例96 K_均值算法
k_algorithm.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
int vectornum;
int vectorsize;
float * datafield;
float * tempcenter;
struct GROUP
{
float * center;//聚类中心坐标
int groupsize;//聚类包含的样本个数
} g , * group;
int K;//聚类中心个数
void initiate ();//读入数据,初始化聚类中心,参数设定默认值
int allocate ();//将模式样本分配给最近的聚类
void showresult ();//显示分类结果
float distance (float * x , float * y);//计算两个向量间的欧氏距离
float data (int i , int j);//从datafield中读取指定位置的值
float * vector (int i);//从datafield中读取指定的样本向量
void write (int i , int j , float data);//向datafield中指定位置写入值
void main ()
{
int i;
initiate ();
for (i = 1 ; i < 50 ; i++)
{
showresult ();
if (allocate () == 1)break;
}
showresult ();
free (datafield);
free (tempcenter);
for (i = 0 ; i < K ; i++)
free (group[i].center);
}
void initiate ()
{
int i , j , size;
float d;
FILE * df;
K = 2;
if ((df = fopen ("data.txt" , "r")) == NULL)
{
printf ("Cannot open file\n");
exit (1);
}
fscanf (df , "%5d" , &vectornum);
fscanf (df , "%5d" , &vectorsize);
size = vectornum * (vectorsize + 1);
datafield = (float *) calloc (size , sizeof (d));
tempcenter = (float *) calloc (vectorsize , sizeof (d));
for (i = 0 ; i < vectornum ; i++)
{
for (j = 0 ; j < vectorsize ; j++)
{
fscanf (df , "%10f" , &d);
write (i , j + 1 , d);
}
write (i , 0 , -1);
}
if (feof (df)) printf (" File read error! ");
fclose (df);
printf ("请输入聚类数:\n");
scanf ("%d" , &K);
group = (struct GROUP *) calloc (K , sizeof (g));
for (i = 0 ; i < K ; i++)
{
group[i].center = (float*) calloc ((vectorsize) , sizeof (d));
group[i].groupsize = 0;
}
for (i = 0 ; i < K ; i++)
{
for (j = 0 ; j < vectorsize ; j++)
{
*(group[i].center + j) = data (i , j + 1);
}
}
}
int allocate()
{
int i , j , k , flag , index;
float D , D1 , sum;
for (i = 0 ; i < K ; i++)
{
group[i].groupsize = 0;
}
for (i = 0 ; i < vectornum ; i++)//按距离分配到各聚类域
{
D = distance (group[0].center , vector(i));
k = 0;
for(j = 1 ; j < K ; j++)
{
D1 = distance (group[j].center , vector(i));
if(D > D1)
{
k = j;
D = D1;
}
}
write (i , 0 , (float) k);
group[k].groupsize++;
}
flag = 1;
for (index = 0 ; index < K ; index++)//计算新的聚类中心
{
for (j = 0 ; j < vectorsize ; j++)
tempcenter[j] = 0.0;
sum = (float) group[index].groupsize;
for (i = 0 ; i < vectornum ; i++)
{
if (index == (int) data (i , 0))
for (j = 0 ; j < vectorsize ; j++)
tempcenter[j] += data (i , j + 1) / sum;
}
for (j = 0 ; j < vectorsize ; j++)
{
if ( tempcenter[j] != group[index].center[j])
{
group[index].center[j] = tempcenter[j];
flag = 0;
}
}
}
return flag;
}
void showresult()
{
int i , j , k;
for (i = 0 ; i < K ; i++)
{
printf ("\n第%3d组聚类中心坐标为:" , i + 1);
for (j = 0 ; j < vectorsize ; j++)
printf (" %10f " , group[i].center[j]);
printf (" \n聚类包含的样本点的坐标为:\n ");
for (j = 0 ; j < vectornum ; j++)
{
if (data (j , 0) == i)
{
for (k = 0 ; k < vectorsize ; k++)
{
printf (" %10f " , data (j , k + 1));
}
printf (" \n ");
}
}
}
printf (" \n ");
}
float data (int i , int j)
{
return *(datafield + i * (vectorsize + 1) + j);
}
void write (int i , int j , float data)
{
*(datafield + i * (vectorsize + 1) + j) = data;
}
float * vector (int i)
{
return datafield + i * (vectorsize + 1) + 1;
}
float distance (float * x , float * y)
{
int i;
float z;
for (i = 0 , z = 0 ; i < vectorsize ; i++)
z = z + ((* (x + i)) - (* (y + i)))*((* (x + i))-(* (y + i)));
return (float) sqrt (z);
}
数据文件 data.txt
8 2 0.000000 0.000000 1.000000 1.000000 2.000000 2.000000 4.000000 3.000000 5.000000 3.000000 4.000000 4.000000 5.000000 4.000000 6.000000 5.000000 end
运行
trust100@ubuntu:~/test/clanguage$ ./a.out
请输入聚类数:
10
第 1组聚类中心坐标为: 0.000000 0.000000
聚类包含的样本点的坐标为:
第 2组聚类中心坐标为: 1.000000 1.000000
聚类包含的样本点的坐标为:
第 3组聚类中心坐标为: 2.000000 2.000000
聚类包含的样本点的坐标为:
第 4组聚类中心坐标为: 4.000000 3.000000
聚类包含的样本点的坐标为:
第 5组聚类中心坐标为: 5.000000 3.000000
聚类包含的样本点的坐标为:
第 6组聚类中心坐标为: 4.000000 4.000000
聚类包含的样本点的坐标为:
第 7组聚类中心坐标为: 5.000000 4.000000
聚类包含的样本点的坐标为:
第 8组聚类中心坐标为: 6.000000 5.000000
聚类包含的样本点的坐标为:
第 9组聚类中心坐标为: 0.000000 0.000000
聚类包含的样本点的坐标为:
第 10组聚类中心坐标为: 0.000000 0.000000
聚类包含的样本点的坐标为:
第 1组聚类中心坐标为: 0.000000 0.000000
聚类包含的样本点的坐标为:
0.000000 0.000000
第 2组聚类中心坐标为: 1.000000 1.000000
聚类包含的样本点的坐标为:
1.000000 1.000000
第 3组聚类中心坐标为: 2.000000 2.000000
聚类包含的样本点的坐标为:
2.000000 2.000000
第 4组聚类中心坐标为: 4.000000 3.000000
聚类包含的样本点的坐标为:
4.000000 3.000000
第 5组聚类中心坐标为: 5.000000 3.000000
聚类包含的样本点的坐标为:
5.000000 3.000000
第 6组聚类中心坐标为: 4.000000 4.000000
聚类包含的样本点的坐标为:
4.000000 4.000000
第 7组聚类中心坐标为: 5.000000 4.000000
聚类包含的样本点的坐标为:
5.000000 4.000000
第 8组聚类中心坐标为: 6.000000 5.000000
聚类包含的样本点的坐标为:
6.000000 5.000000
第 9组聚类中心坐标为: 0.000000 0.000000
聚类包含的样本点的坐标为:
第 10组聚类中心坐标为: 0.000000 0.000000
聚类包含的样本点的坐标为:
第 1组聚类中心坐标为: 0.000000 0.000000
聚类包含的样本点的坐标为:
0.000000 0.000000
第 2组聚类中心坐标为: 1.000000 1.000000
聚类包含的样本点的坐标为:
1.000000 1.000000
第 3组聚类中心坐标为: 2.000000 2.000000
聚类包含的样本点的坐标为:
2.000000 2.000000
第 4组聚类中心坐标为: 4.000000 3.000000
聚类包含的样本点的坐标为:
4.000000 3.000000
第 5组聚类中心坐标为: 5.000000 3.000000
聚类包含的样本点的坐标为:
5.000000 3.000000
第 6组聚类中心坐标为: 4.000000 4.000000
聚类包含的样本点的坐标为:
4.000000 4.000000
第 7组聚类中心坐标为: 5.000000 4.000000
聚类包含的样本点的坐标为:
5.000000 4.000000
第 8组聚类中心坐标为: 6.000000 5.000000
聚类包含的样本点的坐标为:
6.000000 5.000000
第 9组聚类中心坐标为: 0.000000 0.000000
聚类包含的样本点的坐标为:
第 10组聚类中心坐标为: 0.000000 0.000000
聚类包含的样本点的坐标为:
实例97 ISODATA算法
isogroup.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
float * datafield;
int vectornum;
int vectorsize;
struct GROUP
{
float * center;
float D;
float variance;
int groupsize;
int flag;//代表这个数组单元是否被占用
};
struct GROUP group[100];
int maxindex;//最大聚类号
int groupnum;
struct CCD//记录各聚类中心的距离
{
float dst;
int g1 , g2;//聚类编号
}ccd , * ccdhead;
float Dst;
void write (int i , int j , float data);//
float data (int i , int j);//
float * vector (int i);//
void initiate ();//
void input ();//
void allocate ();//将模式样本分配给最近的聚类
void converge ();//
void diverge ();//
void renum ();//重新分配聚类号
void showresult ();
float distance (float * x , float * y);
void split (int i , int j);//
void insert (int i , int j , float D);
int K;//预期的聚类中心数目
int Nmin;//每一聚类中最少的样本数目,即如少于此数就不作为一个孤立的聚类
float Ds;//一个聚类域中样本距离分布的标准差
float Dm;//两个聚类中心之间的最小距离,如小于此数,两个聚类进行合并
int L;//在于此迭代运算中可以合并的聚类中心的最多对数
int I;//迭代运算的次数序号
void main ()
{
int i;
initiate ();//读入数据,初始化聚类中心,参数设定默认值
for (i = 1 ; ; i++)
{
input ();//显示、修改参数
allocate ();//完成第2-6步
if (i == I)
{
Dm = 0;
converge ();
break;
}
if (groupnum <= K / 2) diverge ();
else
{
if ((groupnum >= K * 2) | ( i % 2 == 0))
converge ();
else
diverge ();
}
renum ();
}
showresult ();
free (datafield);
free (ccdhead);
for (i = 0 ; i < 100 ; i++)
free (group[i].center);
}
void initiate ()
{
int i , j , size;
FILE * df;
char s[10];
float d;
K = 2;
Nmin = 1;
Ds = 1;
Dm = 4;
L = 1;
I = 5;
maxindex = groupnum = 1;
if ((df = fopen("data.txt" , "r")) == NULL)
{
printf ("Cannot open file\n");
exit (1);
}
fscanf (df , "%5d" , &vectornum);
fscanf (df , "%5d" , &vectorsize);
size = vectornum * (vectorsize + 1);
datafield = (float *) malloc (size * sizeof (float));
for (i = 0 ; i < vectornum ; i++)
{
for (j = 0 ; j < vectorsize ; j++)
{
fscanf (df , "%10f" , &d);
write (i , j + 1 , d);
}
write (i , 0 , -1);
}
fscanf (df , "%10s" , s);
if (strcmp (s , "end") != 0)
{
printf ("\n程序初始化失败!");
exit (1);
}
fclose (df);
for (i = 0 ; i < 100 ; i++)
{
group[i].flag = 0;
group[i].center = (float *) malloc ((vectorsize) * sizeof (float));
group[i].groupsize = 0;
group[i].variance = 0;
group[i].D = 0;
}
for (i = 0 ; i < groupnum ; i++)
{
for (j = 0 ; j < vectorsize ; j++)
{
* (group[i].center + j) = data(i , j + 1);///////////////////////////////////////////
}
group[i].flag = 1;
}
}
void input ()
{
char choice;
printf ("\n\n现用的参数取值:\n");
printf ("K = %d\n,Nmin=%d\n,Ds=%f\n,Dm=%f\n,L=%d\n,I=%d\n",K,Nmin,Ds,Dm,L,I);
showresult();
printf ("是否需要进行修改?(Y/N)\n");
scanf("%s" , & choice);
choice = toupper (choice);
if (choice == 'Y')
{
printf ("\n请输入预期的聚类中心数目:");
scanf ("%d" , &K);
printf ("\n请输入每一聚类域中最少样本数:");
scanf ("%d" , &Nmin);
printf ("\n请输入一个聚类域中样本距离分布的标准差:");
scanf ("%f" , &Ds);
printf("\n请输入两聚类中心之间的最小距离:");
scanf ("%f" , &Dm);
printf ("\n请输入一次迭代运算中可以合并的聚类中心的最多数目:");
scanf ("%d" , &L);
printf ("\n请输入最大迭代次数:");
scanf ("%d" , &I);
}
}
void allocate ()
{
int i , j , k , num , index;
float D , D1 , sum;
for (i = 0 ; i < 100 ; i++)//为各聚类中心值清零
{
group[i].D = 0;
group[i].groupsize = 0;
group[i].variance = 0;
}
for (i=0 ; i < vectornum ; i++)//按距离分配到各聚类域
{
D = distance (group[0].center , vector (i));
k = 0;
for (j = 1 ; j < groupnum ; j++)
{
D1 = distance (group[j].center , vector (i));
if (D > D1)
{
k = j;
D = D1;
}
}
write (i , 0 , (float) k);
group[k].groupsize++;
}
num = groupnum;
for (i = 0 ; i < num ; i++)//当聚类中样本个数小于规定值时撤销聚类
{
if (group[i].groupsize < Nmin)
{
group[i].flag = 0;
group[i].groupsize = 0;
for (j = 0 ; j < vectornum ; j++)
{
if (data (j , 0) == i)
{
write (j , 0 , -1.0);
}
}
groupnum--;
}
}
for (i = 0 ; i < 100 ; i++)//为各聚类中心值清零
{
for (j = 0 ; j < vectorsize ; j++)
* (group[i].center + j) = 0;
}
for (i = 0 ; i < vectornum ; i++)//计算新的聚类中心
{
index = (int) data (i , 0);
if (index != -1)
{
sum = (float) group[index].groupsize;
for (j = 0 ; j < vectorsize ; j++)
{
* (group[index].center + j) = * (group[index].center + j) + data(i , j + 1) / sum;
}
}
}
for (i = 0 ; i < vectornum ; i++)//计算各样点到聚类中心距离
{
index = (int) data (i , 0);
if (index != -1)
{
sum = (float) group[index].groupsize;
D = distance (group[index].center , vector (i));
group[index].D = group[index].D + D / sum;
}
}
Dst = 0;
for (i = 0 ; i < maxindex ; i++)
{
if (group[i].flag != 0)
Dst = Dst + group[i].D;
}
Dst = Dst / groupnum;
}
void diverge ()
{
float newvar , oldvar , center;
int i , j , k , l , flag;
flag = 0;
for (i = 0 ; i < maxindex ; i++)
{
if (group[i].flag != 0)
{
oldvar = 0;//标准差
for (j = 0 , l = 0 ; j < vectorsize ; j++)
{//计算同一聚类域中各分量对应的标准差中的最大值
newvar = 0;
center = * (group[i].center + j);
for (k = 0 ; k < vectornum ; k++)
{
if (data (k , 0) == i)
newvar = newvar +(center - data(k , j+1))*(center - data(k , j+1));
}
if (newvar > oldvar)
{
oldvar = newvar;
l = j;
}
}
group[i].variance = (float) sqrt( oldvar / group[i].groupsize);
if (group[i].variance > Ds)
{
if ((groupnum <= K/2) | ((group[i].D > Dst) & (group[i].groupsize > 2 * (Nmin + 1))))
{
split (i , l);
flag = 1;
}
}
}
}
if (flag == 0)
converge ();
}
void split (int i , int j)
{
int k , l;
k = maxindex;
group[k].flag = 1;
for (l = 0 ; l < vectorsize ; l++)
{
* (group[k].center + l) = (* (group[i].center + l));
}
* (group[k].center + j) = (* (group[k].center + j) + group[i].variance);
* (group[i].center + j) = (* (group[i].center + j) - group[i].variance);
maxindex++;
groupnum++;
}
void converge ()
{
int i , j , k , h , l;
float D , c1 , c2 , n1 , n2;
ccdhead = (struct CCD *) malloc (sizeof (ccd) * L);
for (i = 0 , k = 0 ; i < maxindex - 1 ; i++)
{
if (group[i].flag != 0)
{
for (j = i + 1 ; j < maxindex ; j++)
{
if (group[j].flag != 0)
{
D = distance (group[i].center , group[j].center);
if (D < Dm)
{
if (k < L)
{
(ccdhead + k)->dst = D;
(ccdhead + k)->g1 = i;
(ccdhead + k)->g2 = j;
k++;
}
else
{
insert (i,j,D);
}
break;
}
}
}
}
}
for (h = 0 ; h < k ;h++)
{
i = (ccdhead + h)->g1;
j = (ccdhead + h)->g2;
n1 = (float) group[i].groupsize;
n2 = (float) group[j].groupsize;
for (l = 0 ; l < vectorsize ; l++)
{
c1 = (* (group[i].center + l));
c2 = (* (group[j].center + l));
* (group[i].center + l) = (n1 * c1 + n2 * c2) / (n1 + n2);
}
group[i].groupsize = (int) (n1 + n2);
for (l = 0 ; l < vectornum ; l++)
if (data(l , 0) == j)
write (l , 0 , (float) i);
group[j].flag = 0;
group[j].groupsize = 0;
groupnum--;
}
}
void insert (int i , int j , float D)
{
int h , l;
for (h = 0 ; h < L ; h++)
{
if (D < (ccdhead + h)->dst)
{
for (l = L - 1 ; l > h ; l--)
{
(ccdhead + l)->dst = (ccdhead + l - 1)->dst;
(ccdhead + l)->g1 = (ccdhead + l - 1)->g1;
(ccdhead + l)->g2 = (ccdhead + l - 1)->g2;
}
(ccdhead + h)->dst = D;
(ccdhead + h)->g1 = i;
(ccdhead + h)->g2 = j;
}
}
}
void renum ()
{
int i , j , k;
for (i = 0 ; i < maxindex - 1 ; i++)
{
if (group[i].flag == 0)
{
for (j = maxindex ; j > i ; j--)
{
if (group[j].flag == 1)
{
group[i].flag = 1;
group[j].flag = 0;
for (k = 0 ; k < vectorsize ; k++)
{
* (group[i].center + k) = (* (group[j].center + k));
* (group[j].center + k) = 0;
}
}
}
}
}
maxindex = groupnum;
}
void showresult ()
{
int i , j , k , l;
for (j = 1 , i = 0 ; i < maxindex ; i++)
{
if (group[i].flag != 0)
{
printf ("第%3d组聚类中心坐标为:" , j ++);
for (k = 0 ; k < vectorsize ; k++)
printf (" %10f " , *(group[i].center + k));
printf (" \n聚类包含的样本点的坐标为:\n ");
for (k = 0 ; k < vectornum ; k++)
{
if (data(k , 0) == i)
{
for (l = 0 ; l < vectorsize ; l++)
{
printf (" %10f " , data(k , l + 1));
}
printf (" \n ");
}
}
}
}
}
float data (int i , int j)
{
return * (datafield + i * (vectorsize + 1) + j);
}
void write (int i , int j , float data)
{
* (datafield + i * (vectorsize + 1) + j) = data;
}
float * vector (int i)
{
return datafield + i * (vectorsize + 1) + 1;
}
float distance (float * x , float * y)
{
int i;
float z;
for (i = 0 , z = 0 ; i < vectorsize ; i++)
z = z + ((* (x + i)) - (* (y + i))) * ((* (x + i))-(* (y + i)));
return (float) sqrt(z);
}
运行
trust100@ubuntu:~/test/clanguage$ ./a.out
现用的参数取值:
K = 2
,Nmin=1
,Ds=1.000000
,Dm=4.000000
,L=1
,I=5
第 1组聚类中心坐标为: 0.000000 0.000000
聚类包含的样本点的坐标为:
是否需要进行修改?(Y/N)
N
现用的参数取值:
K = 2
,Nmin=1
,Ds=1.000000
,Dm=4.000000
,L=1
,I=5
第 1组聚类中心坐标为: 1.378910 2.750000
聚类包含的样本点的坐标为:
0.000000 0.000000
1.000000 1.000000
2.000000 2.000000
4.000000 3.000000
5.000000 3.000000
4.000000 4.000000
5.000000 4.000000
6.000000 5.000000
第 2组聚类中心坐标为: 5.371090 2.750000
聚类包含的样本点的坐标为:
是否需要进行修改?(Y/N)
N
现用的参数取值:
K = 2
,Nmin=1
,Ds=1.000000
,Dm=4.000000
,L=1
,I=5
第 1组聚类中心坐标为: 1.000000 1.000000
聚类包含的样本点的坐标为:
0.000000 0.000000
1.000000 1.000000
2.000000 2.000000
第 2组聚类中心坐标为: 4.800000 3.800000
聚类包含的样本点的坐标为:
4.000000 3.000000
5.000000 3.000000
4.000000 4.000000
5.000000 4.000000
6.000000 5.000000
是否需要进行修改?(Y/N)
N
现用的参数取值:
K = 2
,Nmin=1
,Ds=1.000000
,Dm=4.000000
,L=1
,I=5
第 1组聚类中心坐标为: 1.000000 1.000000
聚类包含的样本点的坐标为:
0.000000 0.000000
1.000000 1.000000
2.000000 2.000000
第 2组聚类中心坐标为: 4.800000 3.800000
聚类包含的样本点的坐标为:
4.000000 3.000000
5.000000 3.000000
4.000000 4.000000
5.000000 4.000000
6.000000 5.000000
是否需要进行修改?(Y/N)
N
现用的参数取值:
K = 2
,Nmin=1
,Ds=1.000000
,Dm=4.000000
,L=1
,I=5
第 1组聚类中心坐标为: 1.000000 1.000000
聚类包含的样本点的坐标为:
0.000000 0.000000
1.000000 1.000000
2.000000 2.000000
第 2组聚类中心坐标为: 4.800000 3.800000
聚类包含的样本点的坐标为:
4.000000 3.000000
5.000000 3.000000
4.000000 4.000000
5.000000 4.000000
6.000000 5.000000
是否需要进行修改?(Y/N)
N
第 1组聚类中心坐标为: 1.000000 1.000000
聚类包含的样本点的坐标为:
0.000000 0.000000
1.000000 1.000000
2.000000 2.000000
第 2组聚类中心坐标为: 4.800000 3.800000
聚类包含的样本点的坐标为:
4.000000 3.000000
5.000000 3.000000
4.000000 4.000000
5.000000 4.000000
6.000000 5.000000
实例98 快速傅立叶变换
fft.c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define PI 3.14159265358979323846
struct COMPLEX
{
float re;
float im;
} cplx , * Hfield , * S , * R , * w;
int n , m;
int ln , lm;
void initiate ();
void dfft ();
void rdfft ();
void showresult ();
void fft (int l , int k);
int reverse (int t , int k);
void W (int l);
int loop (int l);
void conjugate ();
void add (struct COMPLEX * x , struct COMPLEX * y , struct COMPLEX * z);
void sub (struct COMPLEX * x , struct COMPLEX * y , struct COMPLEX * z);
void mul (struct COMPLEX * x , struct COMPLEX * y , struct COMPLEX * z);
struct COMPLEX * Hread(int i , int j);
void Hwrite (int i , int j , struct COMPLEX x);
void main ()
{
initiate ();
printf("\n原始数据:\n");
showresult();
getchar ();
dfft ();
printf("\n快速复利叶变换后的结果:\n");
showresult ();
getchar ();
rdfft ();
printf("\n快速复利叶逆变换后的结果:\n");
showresult ();
getchar ();
free (Hfield);
}
void initiate ()
{//程序初始化操作,包括分配内存、读入要处理的数据、进行显示等
FILE * df;
df = fopen ("data.txt" , "r");
fscanf (df , "%5d" , &n);
fscanf (df , "%5d" , &m);
if ((ln = loop (n)) == -1)
{
printf (" 列数不是2的整数次幂 ");
exit (1);
}
if ((lm = loop (m)) == -1)
{
printf (" 行数不是2的整数次幂 ");
exit (1);
}
Hfield = (struct COMPLEX *) malloc (n * m * sizeof (cplx));
if (fread (Hfield , sizeof (cplx) , m * n , df) != (unsigned) (m * n))
{
if (feof (df)) printf (" Premature end of file ");
else printf (" File read error ");
}
fclose (df);
}
void dfft ()
{//进行二维快速复利叶变换
int i , j;
int l , k;
l = n;
k = ln;
w = (struct COMPLEX *) calloc (l , sizeof (cplx));
R = (struct COMPLEX *) calloc (l , sizeof (cplx));
S = (struct COMPLEX *) calloc (l , sizeof(cplx));
W (l);
for ( i = 0 ; i < m ; i++ )
{//按行进行快速复利叶变换
for (j = 0 ; j < n ; j++)
{
S[j].re = Hread (i , j)->re;
S[j].im = Hread (i , j)->im;
}
fft(l , k);
for (j = 0 ; j < n ; j++)
Hwrite (i , j , R[j]);
}
free (R);
free (S);
free (w);
l = m;
k = lm;
w = (struct COMPLEX *) calloc (l , sizeof (cplx));
R = (struct COMPLEX *) calloc (l , sizeof (cplx));
S = (struct COMPLEX *) calloc (l , sizeof (cplx));
W (l);
for (i = 0 ; i < n ; i++)
{//按列进行快速复利叶变换
for(j = 0 ; j < m ; j++)
{
S[j].re = Hread(j , i)->re;
S[j].im = Hread(j , i)->im;
}
fft(l , k);
for (j = 0 ; j < m ; j++)
Hwrite (j , i , R[j]);
}
free (R);
free (S);
free (w);
}
void rdfft ()
{
conjugate ();
dfft ();
conjugate ();
}
void showresult ()
{
int i , j;
for (i = 0 ; i < m ; i++)
{
printf ( " \n第%d行\n " , i);
for (j = 0 ; j < n ; j++)
{
if (j % 4 == 0) printf (" \n ");
printf(" (%5.2f,%5.2fi) " , Hread (i , j)->re , Hread (i , j)->im);
}
}
}
void fft (int l , int k)
{
int i , j , s , nv , t;
float c;
struct COMPLEX mp , r;
nv = l;
c = (float) l;
c = pow (c , 0.5);
for (i = 0 ; i < k ; i++)
{
for (t = 0 ; t < l ; t += nv)
{
for (j = 0 ; j < nv / 2 ; j++)
{
s = (t + j) >> (k - i -1);
s = reverse(s , k);
r.re = S[t + j].re;
r.im = S[t + j].im;
mul (&w[s] , &S[t + j + nv / 2] , &mp);/////////讲解传递结构指针和结构本身的区别
add (&r , &mp , &S[t + j]);
sub (&r , &mp , &S[t + j + nv / 2]);
}
}
nv = nv >> 1;
}
for (i = 0 ; i < l ; i++)
{
j = reverse(i , k);
R[j].re = S[i].re / c;
R[j].im = S[i].im / c;
}
}
int reverse (int t , int k)
{
int i , x , y;
y = 0;
for (i = 0 ; i < k ; i++)
{
x = t & 1;
t = t >> 1;
y = (y << 1) + x;
}
return y;
}
void W (int l)
{
int i;
float c , a;
c = (float) l;
c = 2 * PI / c;
for (i = 0 ; i < l ; i++)
{
a = (float) i;
w[i].re = (float) cos(a * c);
w[i].im = -(float) sin(a * c);
}
}
int loop (int l)
{//检验输入数据是否为2的整数次幂,如果是返回用2进制表示时的位数
int i , m;
if (l != 0)
{
for (i = 1 ; i < 32 ; i++)
{
m = l >> i;
if (m == 0)
break;
}
if (l == (1 << (i - 1)))
return i - 1;
}
return -1;
}
void conjugate ()
{//求复数矩阵的共轭矩阵
int i , j;
for (i = 0 ; i < m ; i++)
{
for (j = 0 ; j < n ; j++)
{
Hread (i , j)->im *= -1;
}
}
}
struct COMPLEX * Hread (int i , int j)
{//按读矩阵方式返回Hfield中指定位置的指针
return (Hfield + i * n + j);
}
void Hwrite (int i , int j , struct COMPLEX x)
{//按写矩阵方式将复数结构x写到指定的Hfield位置上
(Hfield + i * n + j)->re = x.re;
(Hfield + i * n + j)->im = x.im;
}
void add (struct COMPLEX * x , struct COMPLEX * y , struct COMPLEX * z)
{//定义复数加法
z->re = x->re + y->re;
z->im = x->im + y->im;
}
void sub (struct COMPLEX * x , struct COMPLEX * y , struct COMPLEX * z)
{//定义复数减法
z->re = x->re - y->re;
z->im = x->im - y->im;
}
void mul (struct COMPLEX * x , struct COMPLEX * y , struct COMPLEX * z)
{//定义复数乘法
z->re = (x->re) * (y->re) - (x->im) * (y->im);
z->im = (x->im) * (y->re) + (x->re) * (y->im);
}
data.txt
8 4 €? @ @@ €@ 燖 繞 郂 €? €? €? €? @ €? @@ €? €@ €? 燖 €? 繞 €? 郂 @ @ €? @ @ @ @@ @ €@ @ 燖 @ 繞 @ 郂 @@ @@ €? @@ @ @@ @@ @@ €@ @@ 燖 @@ 繞 @@ 郂
运行
trust100@ubuntu:~/test/clanguage$ ./a.out
原始数据:
第0行
( 0.00, 0.00i) ( 0.00, 1.00i) ( 0.00, 2.00i) ( 0.00, 3.00i)
( 0.00, 4.00i) ( 0.00, 5.00i) ( 0.00, 6.00i) ( 0.00, 7.00i)
第1行
( 1.00, 0.00i) ( 1.00, 1.00i) ( 1.00, 2.00i) ( 1.00, 3.00i)
( 1.00, 4.00i) ( 1.00, 5.00i) ( 1.00, 6.00i) ( 1.00, 7.00i)
第2行
( 2.00, 0.00i) ( 2.00, 1.00i) ( 2.00, 2.00i) ( 2.00, 3.00i)
( 2.00, 4.00i) ( 2.00, 5.00i) ( 2.00, 6.00i) ( 2.00, 7.00i)
第3行
( 3.00, 0.00i) ( 3.00, 1.00i) ( 3.00, 2.00i) ( 3.00, 3.00i)
( 3.00, 4.00i) ( 3.00, 5.00i) ( 3.00, 6.00i) ( 3.00, 7.00i)
快速复利叶变换后的结果:
第0行
( 8.49,19.80i) (-6.83,-2.83i) (-2.83,-2.83i) (-1.17,-2.83i)
( 0.00,-2.83i) ( 1.17,-2.83i) ( 2.83,-2.83i) ( 6.83,-2.83i)
第1行
(-2.83, 2.83i) ( 0.00, 0.00i) ( 0.00, 0.00i) ( 0.00, 0.00i)
( 0.00, 0.00i) ( 0.00, 0.00i) ( 0.00, 0.00i) ( 0.00, 0.00i)
第2行
(-2.83, 0.00i) ( 0.00, 0.00i) ( 0.00, 0.00i) ( 0.00, 0.00i)
( 0.00, 0.00i) ( 0.00, 0.00i) ( 0.00, 0.00i) ( 0.00, 0.00i)
第3行
(-2.83,-2.83i) ( 0.00, 0.00i) ( 0.00, 0.00i) ( 0.00, 0.00i)
( 0.00, 0.00i) ( 0.00, 0.00i) ( 0.00, 0.00i) ( 0.00, 0.00i)
快速复利叶逆变换后的结果:
第0行
( 0.00, 0.00i) ( 0.00, 1.00i) ( 0.00, 2.00i) (-0.00, 3.00i)
( 0.00, 4.00i) (-0.00, 5.00i) ( 0.00, 6.00i) ( 0.00, 7.00i)
第1行
( 1.00, 0.00i) ( 1.00, 1.00i) ( 1.00, 2.00i) ( 1.00, 3.00i)
( 1.00, 4.00i) ( 1.00, 5.00i) ( 1.00, 6.00i) ( 1.00, 7.00i)
第2行
( 2.00, 0.00i) ( 2.00, 1.00i) ( 2.00, 2.00i) ( 2.00, 3.00i)
( 2.00, 4.00i) ( 2.00, 5.00i) ( 2.00, 6.00i) ( 2.00, 7.00i)
第3行
( 3.00, 0.00i) ( 3.00, 1.00i) ( 3.00, 2.00i) ( 3.00, 3.00i)
( 3.00, 4.00i) ( 3.00, 5.00i) ( 3.00, 6.00i) ( 3.00, 7.00i)
实例99 求解野人与传教士问题
AI.C
#include <stdio.h>
#include <stdlib.h>
#define maxloop 100 //最大层数,对于不同的扩展方法自动调整取值
#define pristnum 3
#define slavenum 3
struct SPQ
{
int sr,pr; //船运行一个来回后河右岸的野人、传教士的人数
int sl,pl; //船运行一个来回后河左岸的野人、传教士的人数
int ssr,spr; //回来(由左向右时)船上的人数
int sst,spt; //去时(由右向左时)船上的人数
int loop; //本结点所在的层数
struct SPQ *upnode ,*nextnode;//本结点的父结点和同层的下一个结点的地址
}spq;
int loopnum;//记录总的扩展次数
int openednum;//记录已扩展节点个数
int unopenednum;//记录待扩展节点个数
int resultnum;
struct SPQ *opened;
struct SPQ *oend;
struct SPQ *unopened;
struct SPQ *uend;
struct SPQ *result;
void initiate();
void releasemem();
void showresult();
void addtoopened(struct SPQ *ntx);
int search();
void goon();
int stretch(struct SPQ* ntx);
void recorder();
void main()
{
int flag; //标记扩展是否成功
for( ; ; )
{
initiate();
flag = search ();
if(flag == 1)
{
recorder();
releasemem();
showresult();
goon();
}
else
{
printf("无法找到符合条件的解");
releasemem();
goon();
}
}
}
void initiate()
{
int x;
char choice;
uend = unopened = (struct SPQ*)malloc(sizeof(spq));
if(uend==NULL)
{
printf("\n内存不够!\n");
exit(0);
}
unopenednum=1;
openednum=0;
unopened -> upnode = unopened; //保存父结点的地址以成链表
unopened -> nextnode = unopened;
unopened -> sr = slavenum;
unopened -> pr = pristnum;
unopened -> sl = 0;
unopened -> pl = 0;
unopened -> sst = 0;
unopened -> spt = 0;
unopened -> ssr = 0;
unopened -> spr = 0;
unopened -> loop = 0;
printf("题目:设有n个传教士和m个野人来到河边,打算乘一只船从右岸到左岸去。\n");
printf("该船的负载能力为两人。在任何时候,如果野人人数超过传教士人数,野人\n");
printf("就会把传教士吃掉。他们怎样才能用这条船安全的把所有人都渡过河去?\n");
printf("\n默认的n、m值皆为3\n");
for(;;)
{
printf("\n是否修改?(Y/N)");
scanf("%s",&choice);
choice=toupper(choice);
if(choice=='Y')
{
printf("\n请输入传教士人数");
for(;;)
{
scanf("%d",&x);
if(x>0)
{
unopened -> pr = x;
break;
}
else printf("\n输入值应大于0!\n请重新输入");
}
printf("\n请输入野人人数");
for(;;)
{
scanf("%d",&x);
if(x>0)
{
unopened -> sr = x;
break;
}
else printf("\n输入值应大于0!\n请重新输入");
}
break;
}
if(choice=='N')break;
}
}
int search()
{
int flag;
struct SPQ *ntx; //提供将要扩展的结点的指针
for( ; ; )
{
ntx = unopened; //从待扩展链表中提取最前面的一个
if(ntx->loop == maxloop)
return 0;
addtoopened(ntx); //将ntx加入已扩展链表,并将这个节点从待扩展链表中去掉
flag = stretch(ntx); //对ntx进行扩展,返回-1,0,1
if(flag == 1)
return 1;
}
}
int stretch(struct SPQ *ntx)
{
int fsr , fpr ; //在右岸上的人数
int fsl , fpl ; //在左岸上的人数
int sst , spt ; //出发时在船上的人数
int ssr , spr ; //返回时船上的人数
struct SPQ *newnode;
for (sst = 0 ; sst <= 2 ; sst++) //讨论不同的可能性并判断是否符合条件
{
fsr = ntx -> sr;
fpr = ntx -> pr;
fsl = ntx -> sl;
fpl = ntx -> pl;
if ((sst <= fsr) && (( 2 - sst) <= fpr))//满足人数限制
{
spt = 2 - sst;
fsr = fsr - sst;
fpr = fpr - spt;
if((fpr == 0) && (fsr == 0))//搜索成功
{
newnode = (struct SPQ*) malloc (sizeof(spq));
if(newnode==NULL)
{
printf("\n内存不够!\n");
exit(0);
}
newnode -> upnode = ntx; //保存父结点的地址以成链表
newnode -> nextnode = NULL;
newnode -> sr = 0;
newnode -> pr = 0;
newnode -> sl = opened -> sr;
newnode -> pl = opened -> pr;
newnode -> sst = sst;
newnode -> spt = spt;
newnode -> ssr = 0;
newnode -> spr = 0;
newnode -> loop = ntx -> loop + 1;
oend -> nextnode = newnode;
oend = newnode;
openednum++;
return 1;
}
else if ((fpr - fsr) * fpr >= 0) //判断是否满足传教士人数必须大于或等于野人人数
{
fsl = fsl + sst;
fpl = fpl + spt;
for (ssr = 0 ; ssr <= 1 ; ssr++) //返回
{
int ffsl , ffpl;
if ((ssr <= fsl) && ((1 - ssr) <= fpl))
{
spr = 1 - ssr;
ffsl = fsl - ssr;
ffpl = fpl - spr;
if ((ffpl - ffsl) * ffpl >= 0)
{ //若符合条件则分配内存并付值
int ffsr , ffpr;
ffsr = fsr + ssr;
ffpr = fpr + spr;
newnode = (struct SPQ*) malloc (sizeof(spq));
if(newnode==NULL)
{
printf("\n内存不够!\n");
exit(0);
}
newnode -> upnode = ntx; //保存父结点的地址以成链表
newnode -> sr = ffsr;
newnode -> pr = ffpr;
newnode -> sl = ffsl;
newnode -> pl = ffpl;
newnode -> sst = sst;
newnode -> spt = spt;
newnode -> ssr = ssr;
newnode -> spr = spr;
newnode -> loop = ntx -> loop + 1;
uend -> nextnode = newnode;
uend = newnode;
unopenednum++;
}
}
}
}
}
}
return 0;
}
void addtoopened(struct SPQ *ntx)
{
unopened = unopened -> nextnode;
unopenednum--;
if (openednum == 0 )
oend = opened = ntx;
oend -> nextnode = ntx;
oend = ntx;
openednum++;
}
void recorder()
{
int i , loop;
struct SPQ *newnode;
struct SPQ *ntx;
loop = oend -> loop;
ntx = oend;
resultnum = 0;
for( i = 0 ; i <= loop ; i++ )
{
newnode = (struct SPQ*) malloc (sizeof(spq));
if(newnode==NULL)
{
printf("\n内存不够!\n");
exit(0);
}
newnode -> sr = ntx -> sr;
newnode -> pr = ntx -> pr;
newnode -> sl = ntx -> sl;
newnode -> pl = ntx -> pl;
newnode -> sst = ntx -> sst;
newnode -> spt = ntx -> spt;
newnode -> ssr = ntx -> ssr;
newnode -> spr = ntx -> spr;
newnode -> nextnode = NULL;
ntx = ntx -> upnode;
if(i == 0)
result = newnode;
newnode -> nextnode = result;
result = newnode;
resultnum++;
}
}
void releasemem()
{
int i;
struct SPQ* nodefree;
for ( i = 1 ; i < openednum ; i++ )
{
nodefree = opened;
opened = opened -> nextnode;
free(nodefree);
}
for ( i = 0 ; i < unopenednum ; i++ )
{
nodefree = unopened;
unopened = unopened -> nextnode;
free(nodefree);
}
}
void showresult()
{
int i;
int fsr , fpr ; //在右岸上的人数
int fsl , fpl ; //在左岸上的人数
struct SPQ* nodefree;
printf("%d个传教士",result -> pr);
printf("%d个野人",result -> sr);
printf("%d个传教士",result -> pl);
printf("%d个野人",result -> sl);
for ( i = 1 ; i < resultnum ; i++ )
{
nodefree = result;
result = result -> nextnode;
free(nodefree);
printf("\n\n\t左岸人数 船上人数及方向 右岸人数\n");
printf("第%d轮\n",i);
fpl = result -> pl - result -> spt + result -> spr;
fpr = result -> pr - result -> spr;
fsl = result -> sl - result -> sst + result -> ssr;
fsr = result -> sr - result -> ssr;
printf("传教士%8d%8d\t<-\t%8d\n",fpl,result -> spt,fpr);
printf("野 人%8d%8d\t<-\t%8d\n",fsl,result -> sst,fsr);
printf("传教士%8d%8d\t->\t%8d\n",result -> pl,result -> spr,result -> pr - result -> spr);
printf("野 人%8d%8d\t->\t%8d\n",result -> sl,result -> ssr,result -> sr - result -> ssr);
}
printf("\n全体传教士和野人全部到达对岸");
free(result);
}
void goon()
{
char choice;
for(;;)
{
printf("是否继续?(Y/N)\n");
scanf ("%s" , &choice);
choice=toupper(choice);
if(choice=='Y')break;
if(choice=='N')exit(0);
}
}
运行
trust100@ubuntu:~/test/clanguage$ ./a.out
题目:设有n个传教士和m个野人来到河边,打算乘一只船从右岸到左岸去。
该船的负载能力为两人。在任何时候,如果野人人数超过传教士人数,野人
就会把传教士吃掉。他们怎样才能用这条船安全的把所有人都渡过河去?
默认的n、m值皆为3
是否修改?(Y/N)N
3个传教士3个野人0个传教士0个野人
左岸人数 船上人数及方向 右岸人数
第1轮
传教士 0 1 <- 2
野 人 0 1 <- 2
传教士 0 1 -> 2
野 人 1 0 -> 2
左岸人数 船上人数及方向 右岸人数
第2轮
传教士 0 1 <- 2
野 人 1 1 <- 1
传教士 0 1 -> 2
野 人 2 0 -> 1
左岸人数 船上人数及方向 右岸人数
第3轮
传教士 0 2 <- 1
野 人 2 0 <- 1
传教士 2 0 -> 1
野 人 1 1 -> 1
左岸人数 船上人数及方向 右岸人数
第4轮
传教士 2 1 <- 0
野 人 1 1 <- 1
传教士 2 1 -> 0
野 人 2 0 -> 1
左岸人数 船上人数及方向 右岸人数
第5轮
传教士 2 1 <- 0
野 人 2 1 <- 0
传教士 3 0 -> 0
野 人 3 0 -> 0
全体传教士和野人全部到达对岸是否继续?(Y/N)
Y
题目:设有n个传教士和m个野人来到河边,打算乘一只船从右岸到左岸去。
该船的负载能力为两人。在任何时候,如果野人人数超过传教士人数,野人
就会把传教士吃掉。他们怎样才能用这条船安全的把所有人都渡过河去?
默认的n、m值皆为3
是否修改?(Y/N)N
3个传教士3个野人0个传教士0个野人
左岸人数 船上人数及方向 右岸人数
第1轮
传教士 0 1 <- 2
野 人 0 1 <- 2
传教士 0 1 -> 2
野 人 1 0 -> 2
左岸人数 船上人数及方向 右岸人数
第2轮
传教士 0 1 <- 2
野 人 1 1 <- 1
传教士 0 1 -> 2
野 人 2 0 -> 1
左岸人数 船上人数及方向 右岸人数
第3轮
传教士 0 2 <- 1
野 人 2 0 <- 1
传教士 2 0 -> 1
野 人 1 1 -> 1
左岸人数 船上人数及方向 右岸人数
第4轮
传教士 2 1 <- 0
野 人 1 1 <- 1
传教士 2 1 -> 0
野 人 2 0 -> 1
左岸人数 船上人数及方向 右岸人数
第5轮
传教士 2 1 <- 0
野 人 2 1 <- 0
传教士 3 0 -> 0
野 人 3 0 -> 0
实例100 简单专家系统
classify.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct SUBLINK
{
int index;
struct SUBLINK *next;
}sublink;
struct NODE
{
char feature[20];
int upnnum;
struct SUBLINK *upnode;
int fullfill;
int type;
int state;
int sonnum;
struct SUBLINK *sonnode;
}node;
#define MAXNUM 1000
struct NODE *nodelink[MAXNUM];
int nodenum;
void initiate();
void quarry();
void modify();
int extend(struct NODE *ntx);
int showfault() ;
void store();
void main()
{
int flag;
initiate();
for(;;)
{
printf("\n\t请选择操作:\n\n\t1、查询;\n\n\t2、添加新知识;\n\n\t3、退出程序.\n\n\t");
scanf("%d",&flag);
switch(flag)
{
case 1:
quarry();
break;
case 2:
modify();
break;
case 3:
store();
default:
printf("\n输入错误,请重新输入\n");
}
}
}
void initiate()//初始化
{
int i , j;
char s[10];
FILE *kf;
struct NODE *newnode;
struct SUBLINK *newlink , *oldlink;
if((kf = fopen("knowledgestore.txt" , "r")) == NULL)
{
printf("Cannot create/open file");
exit(1);
}
fscanf(kf , "%5d" , &nodenum);
for(i=0 ; i < nodenum ; i++)
{
newnode = (struct NODE*)malloc (sizeof(node));
if(newnode == NULL)
{
printf("\n内存不够!\n");
exit(0);
}
fscanf(kf , "%20s" , newnode->feature);
fscanf(kf , "%5d" , &newnode->upnnum);
for(j=0 ; j<newnode->upnnum ; j++)
{
newlink = (struct SUBLINK*) malloc (sizeof(sublink));
if(newlink == NULL)
{
printf("\n内存不够!\n");
exit(0);
}
fscanf(kf , "%5d" , &newlink->index);
if(j == 0)
newnode->upnode = oldlink = newlink;
newlink->next = NULL;
oldlink->next = newlink;
oldlink = newlink;
}
newnode->fullfill = 0;
newnode->state = 0;
fscanf(kf , "%5d" , &newnode->type);
fscanf(kf , "%5d" , &newnode->sonnum);
for(j=0 ; j < newnode->sonnum ; j++)
{
newlink = (struct SUBLINK*)malloc(sizeof(sublink));
if(newlink == NULL)
{
printf("\n内存不够!\n");
exit(0);
}
fscanf(kf , "%5d" , &newlink->index);
if(j == 0)
newnode->sonnode = oldlink = newlink;
newlink->next = NULL;
oldlink->next = newlink;
oldlink = newlink;
}
nodelink[i] = newnode;
}
fscanf(kf , "%10s" , s);
if(strcmp(s , "end") != 0)
{
printf("\n程序初始化失败!");
exit(0);
}
}
void quarry()
{
struct NODE *ntx;
char feature[100];
int i , flag;
for(;;)
{
flag = 0;
printf("\n请输入动物的特征:");
scanf("%s" , feature);
for(i = 0 ; i < nodenum ; i++)
{
ntx = nodelink[i];
if(strstr(feature,ntx->feature) != NULL)
{
ntx->state = 1;
flag = extend(ntx);
}
}
if(flag >= 1)
{
for(i = 0 ; i < nodenum ; i++)
{
nodelink[i]->fullfill = 0;
nodelink[i]->state = 0;
}
break;
}
if(flag == 0)
if(showfault() == 0)break;
}
}
int extend(struct NODE *ntx)
{
int i , index;
int flag;
struct NODE *nextone;
struct SUBLINK *son;
if(ntx->sonnum == 0)
{
printf("\n结果为%20s\n" , ntx->feature);
return 1;
}
son = ntx->sonnode;
flag = 0;
for(i = 0 ; i < (ntx->sonnum) ; i++)
{
index = son->index;
nextone = nodelink[index];
if(nextone->type == 0)//或节点
{
if(nextone->state != 1)
{
nextone->state = 1;
printf("\n表明具有%20s特征" , nextone->feature);
flag += extend(nextone);
}
}
else
{
nextone->fullfill++;
if(nextone->fullfill == nextone->upnnum)
{
nextone->state = 1;
printf("\n表明具有%20s特征" , nextone->feature);
flag =+ extend(nextone);
}
}
son = son->next;
}
return flag;
}
void modify()
{
int i ;
char choice , feature[100];
struct NODE *ntx , *newnode;
struct SUBLINK *endl , *newl;
newnode = (struct NODE*)malloc(sizeof(node));
if(newnode == NULL)
{
printf("\n内存不够!\n");
exit(0);
}
newnode->sonnum = 0;
newnode->upnnum = 0;
newnode->fullfill = 0;
printf("\n请输入新特征\n");
scanf("%s",newnode->feature);
printf("新特征类型:\n与节点(1),或节点(0)");
scanf("%d" , &newnode->type);
newnode->state = 0;
newnode->fullfill = 0;
for(;;)
{
printf("\n是否为叶节点?(Y/N)\n");
scanf("%s" , &choice);
choice = toupper(choice);
if(choice == 'N')
{
printf("\n请输入新特征描述的对象\n");
scanf("%s" , feature);
for(i = 0 ; i < nodenum ; i++)
{
ntx = nodelink[i];
if(strstr(feature,ntx->feature) != NULL)
{
newl = (struct SUBLINK*) malloc (sizeof(sublink));
if(newl == NULL)
{
printf("\n内存不够!\n");
exit(0);
}
if(newnode->sonnum == 0)
newnode->sonnode = endl = newl;
newl->index = i;
endl->next = newl;
endl = newl;
newl->next = NULL;
newnode->sonnum++;
/////////////////////////////////将信息写入子节点
newl = (struct SUBLINK*) malloc (sizeof(sublink));
if(newl == NULL)
{
printf("\n内存不够!\n");
exit(0);
}
if(ntx->upnnum == 0)
ntx->upnode = endl = newl;
newl->index = nodenum;
newl->next = ntx->upnode;
ntx->upnode = newl;
ntx->upnnum++;
}
}
break;
}
if(choice == 'Y')break;
}
for(;;)
{
printf("\n是否为顶点?(Y/N)\n");
scanf("%s" , &choice);
choice = toupper(choice);
if(choice == 'N')
{
printf("\n请输入对新对象的描述\n");
scanf("%s" , feature);
for(i = 0 ; i < nodenum ; i++)
{
ntx = nodelink[i];
if(strstr(feature , ntx->feature)!=NULL)
{
newl = (struct SUBLINK*) malloc (sizeof(sublink));
if(newl == NULL)
{
printf("\n内存不够!\n");
exit(0);
}
if(newnode->upnnum == 0)
newnode->upnode = endl = newl;
newl->index = i;
endl->next = newl;
endl = newl;
newl->next = NULL;
newnode->upnnum++;
///////////////////////////////将信息写入父节点
newl = (struct SUBLINK*) malloc (sizeof(sublink));
if(newl == NULL)
{
printf("\n内存不够!\n");
exit(0);
}
if(ntx->sonnum == 0)
ntx->sonnode = endl = newl;
newl->index = nodenum;
newl->next = ntx->sonnode;
ntx->sonnode = newl;
ntx->sonnum++;
}
}
break;
}
if(choice == 'Y')break;
}
nodelink[nodenum] = newnode;
nodenum++;
}
void store()
{
int i , j;
char s[10];
FILE *kf;
struct NODE *writenode;
struct SUBLINK *newlink , *oldlink;
if((kf = fopen("knowledgestore.txt" , "w")) == NULL)
{
printf("Cannot create/open file");
exit(1);
}
fprintf(kf , "%5d" , nodenum);
for(i = 0 ; i < nodenum ; i++)
{
writenode = nodelink[i];
fprintf(kf , "%20s" , writenode->feature);
fprintf(kf , "%5d" , writenode->upnnum);
newlink = writenode->upnode;
for(j = 0 ; j < writenode->upnnum ; j++)
{
fprintf(kf , "%5d" , newlink->index);
oldlink = newlink;
newlink = newlink->next;
free(oldlink);
}
fprintf(kf , "%5d" , writenode->type);
fprintf(kf , "%5d" , writenode->sonnum);
newlink = writenode->sonnode;
for(j = 0 ; j < writenode->sonnum ; j++)
{
fprintf(kf , "%5d" , newlink->index);
oldlink = newlink;
newlink = newlink->next;
free(oldlink);
}
free(writenode);
}
strcpy(s , "end");
fprintf(kf , "%10s" , s);
fclose(kf);
exit(0);
}
int showfault()
{
char choice;
for(;;)
{
printf("是否继续?(Y/N)\n");
scanf("%s" , &choice);
while(choice == '10');
choice = toupper(choice);
if(choice == 'Y')return 1;
if(choice == 'N')exit(0);
}
}