不确定有穷状态自动机的确定化实验报告Word文档格式.docx
《不确定有穷状态自动机的确定化实验报告Word文档格式.docx》由会员分享,可在线阅读,更多相关《不确定有穷状态自动机的确定化实验报告Word文档格式.docx(17页珍藏版)》请在冰豆网上搜索。
![不确定有穷状态自动机的确定化实验报告Word文档格式.docx](https://file1.bdocx.com/fileroot1/2022-12/9/cabc12b8-fe05-4e0e-8c4c-51c6a61a7660/cabc12b8-fe05-4e0e-8c4c-51c6a61a76601.gif)
stdlib.h>
malloc.h>
stdio.h>
conio.h>
#defineN20//用于控制数组的最大长度
//用邻接表存储NFA和DFA的状态字母后继
typedefstructadjvex
{//定义邻接表的邻接点域的数据表示
charnextstate;
//头结点状态的后继状态
chararc;
//弧
structadjvex*next;
//指向该头结点状态的下一个后继状态的指针
}adjvex;
typedefstructheadvex
{//定义邻接表的头部的数据表示
charstate;
//状态
adjvex*firstarc;
//指向第一个后继状态的指针
}headvex;
//定义两个邻接表的头部,为全局数组
headvexNFA[N];
//用邻接表存储的NFA
headvexDFA[N];
//用邻接表存储的DFA
charAlp[N];
//存储需要输入的行为集,即字母表
voidmain()
{
voiddesignby();
//函数声明
voidclosure(chars,charset[N]);
//求e_closure闭包函数
voidSpecial(charDFA_start[N],charnew_state[N][N]);
//确定化函数
designby();
inti,j;
charNFA_start[N];
//存放NFA的初态
charDFA_start[N];
//存放DFA的初态
charNFA_final[N];
//存放NFA的终态
charDFA_final[N];
//存放DFA的终态
charnew_state[N][N];
//存放DFA的I的二维数组每一行为一个原NFA的一个新的状态集,e-closure(move(I,a))
for(i=0;
i<
N;
i++)
{
NFA[i].state='
#'
;
NFA[i].firstarc=NULL;
DFA[i].state='
DFA[i].firstarc=NULL;
Alp[i]='
NFA_start[i]='
DFA_start[i]='
NFA_final[i]='
DFA_final[i]='
for(j=0;
j<
j++)
new_state[i][j]='
}
intm,n;
printf("
请输入NFA:
状态的个数:
[]\b\b\b"
);
scanf("
%d"
&
n);
fflush(stdin);
状态转换个数:
m);
请输入各状态:
(状态,0/1/2),终态输2,非初终态输1,初态输0.\n"
//创建邻接表
intf;
n;
i++)//n个状态的输入,依次存储到已开辟空间的邻接表头结点中,并根据状态分类装入NFA的初态终态数组中.
printf("
状态%d:
"
i+1);
scanf("
%c,%d"
NFA[i].state,&
f);
fflush(stdin);
if(f==0)//输入状态若为初态,依次存入到NFA_start[N]数组中
{
for(j=0;
N&
&
NFA_start[j]!
='
j++);
NFA_start[j]=NFA[i].state;
}
if(f==2)//输入状态若为终态,依次存入到NFA_final[N]数组中
NFA_final[j]!
NFA_final[j]=NFA[i].state;
输入完毕!
\n\n"
请输入状态转换函数:
(状态1,状态2,输入字符)\n"
adjvex*p;
//定义一个指向adjvex的指针p
charfrom,to,arc;
intk;
m;
i++)//m个转换函数的输入,开辟空间并依次存储至相应头结点状态的邻接表中.
状态转换%d:
%c,%c,%c"
from,&
to,&
arc);
p=(adjvex*)malloc(sizeof(adjvex));
p->
nextstate=to;
arc=arc;
for(k=0;
NFA[k].state!
=from;
k++);
//结束时k的值即为匹配状态所在的头结点
next=NFA[k].firstarc;
//前插法插入结点到头结点后
NFA[k].firstarc=p;
if(arc!
$'
)//输入字符不为空,保存到Alps[N]字母表中
Alp[j]!
j++)
if(arc==Alp[j])
break;
//存在则跳出,结束不保存
//上循环结束的两个可能:
1、该输入字符已经存在于字母表中不存跳出,则下面的if也不会成立;
//2、从0开始到#结束都没找不到一样的字母,结束for,记下了j.
if(Alp[j]=='
)Alp[j]=arc;
//求所有NFA_start[N]中所有初态的closure形成总的初态DFA_start[N]
//charstart[N][N];
//for(i=0;
//for(j=0;
//start[i][j]='
NFA_start[i]!
i++)//依次对每个NFA初态求等价状态放在二维数组中
//closure(NFA_start[i],DFA_start);
/*
i++)//将start二维数组变到一位数组DFA_start[N]中
start[i][j]!
k=0;
for(k=0;
DFA_start[k]!
=start[i][j]&
DFA_start[k]!
k++);
if(DFA_start[k]=='
)DFA_start[k]=start[i][j];
elsecontinue;
*/
k=0;
while(NFA[k].state!
=NFA_start[0])
k++;
closure(NFA[k].state,DFA_start);
//求初态的e_closure闭包
//for(intz=0;
z<
z++)
//printf("
%4c%4c\n"
NFA_start[z],DFA_start[z]);
Special(DFA_start,new_state);
//有DFA_start[N],即为new_state[0]通过对NFA[N]邻接表依次求
//for(z=0;
//{
//printf("
%s\n"
new_state[z]);
//}
i<
N&
new_state[i][0]!
i++)//寻找DFA的终态
j<
new_state[i][j]!
for(f=0;
f<
NFA_final[f]!
f++)
if(new_state[i][j]==NFA_final[f])
{
DFA_final[k]=i+65;
k++;
}
if(new_state[i][j]==NFA_final[f])
break;
//NFA和DFA的输出:
确定化后的DFA如下所示:
\n"
"
Alp[i]!
i++)
%3c"
Alp[i]);
初终"
DFA[i].state!
i++)//以矩阵形式输出DFA
%4c"
DFA[i].state);
Alp[j]!
p=DFA[i].firstarc;
while(p)
{
if(p->
arc==Alp[j])
printf("
p->
nextstate);
else
p=p->
next;
}
if(p==NULL)
printf("
k<
DFA_final[k]!
k++)
if(DFA[i].state==DFA_final[k])
if(DFA_final[k]=='
)
printf("
0"
else
1"
每个新的状态对应的原状态子集如下:
//输出对应的NFA子集
i+65);
{"
new_state[i][j+1]!
%c,"
new_state[i][j]);
%c}"
新的终态如下:
DFA_final[i]!
DFA_final[i]);
}
voidclosure(chars,charset[N])//找一个状态s经过任意连续个的空弧所到达的等价状态的集合set[N](包括自身即为0条空弧)
set[i]!
i++)//将自身存储到set[N]中,0条空弧
if(set[i]==s)
break;
if(set[i]=='
set[i]=s;
for(j=0;
NFA[j].state!
=s;
//查找相应状态所在的邻接表的头结点状态位置j
p=NFA[j].firstarc;
//指针p指向该头结点状态的第一个后继状态
while(p)
if(p->
arc=='
closure(p->
nextstate,set);
//若为空弧的话,递归进入该后继状态所对应的头结点状态处依次查找其空弧后继,查找结束回到上一层后继状态继续查找
p=p->
//查看该头结点状态的下一个后继状态
return;
voidmove(charFrom[N],chararc,charTo[N])//找一个状态集From[N]的所有状态的arc后继状态的集合To[N]
inti,j,k,t=0;
j=0;
//首先定义j为0
From[i]!
i++)//依次对其中的每一个状态求move,直至结束
NFA[k].state!
=From[i];
p=NFA[k].firstarc;
while(p)//逐个后继状态往后判断后继结束,每次将弧为arc的状态保存到To[N]中
if(p->
arc==arc)
for(k=0;
k<
To[k]!
k++)
if(To[k]==p->
nextstate)
{
p=p->
break;
//该状态若已存在To[N]中,跳出循环不保存,移动指针查看下一个后继状态
}
if(To[k]=='
)//直达结束没有发现已经存入,
To[t++]=p->
nextstate;
elsep=p->
voidOrder(chara[N])
//由小到大对数组中的每个字符排序
chartemp;
a[i]!
for(j=i+1;
a[j]!
if(a[j]<
a[i])
temp=a[i];
a[i]=a[j];
a[j]=temp;
voidSpecial(charDFA_start[N],charnew_state[N][N])
charTo1[N],To2[N];
charorder1[N],order2[N];
To1[i]='
To2[i]='
DFA_start[i]!
new_state[0][i]=DFA_start[i];
//将DFA_start[N]复制到new_state[0],作为一个状态
intst,k,t;
for(st=0;
st<
new_state[st][0]!
st++)
DFA[st].state=st+65;
for(i=0;
Alp[i]!
To1[k]='
To2[k]='
//每次使用TO1,To2都要清除原有数据
move(new_state[st],Alp[i],To1);
To1[j]!
j++)//循环求状态集的closure闭包(求每一个状态的closure时,都会对上一个状态得到的To2[N]从头找不相同的存进去)
closure(To1[j],To2);
new_state[j][0]!
{//将new_state和closure(move(I,a))转存到两个新数组中,排序比较是否已经存在此状态集合,以防出错
order1[k]=new_state[j][k];
order2[k]=To2[k];
Order(order1);
Order(order2);
//比较是否相等
order1[k]!
order2[k]!
if(order1[k]!
=order2[k])break;
if(order1[k]==order2[k])break;
//前面比较一直相等,最后第k个也为#,同时结束,说明相同
if(new_state[j][0]=='
)//不存在与新状态相等的状态,将其存入最后一行new_state[j]
for(t=0;
t<
To2[t]!
t++)
new_state[j][t]=To2[t];
p=(adjvex*)malloc(sizeof(adjvex));
//为这个状态转换创建一个结点
p->
nextstate=j+65;
arc=Alp[i];
next=DFA[st].firstarc;
DFA[st].firstarc=p;
voiddesignby()
\n\t\t编译原理实验
(二)\n\n"
\t实验名称:
不确定有穷状态自动机的确定化.\n"
\t实验目的:
输入:
非确定有穷状态自动机NFA\n"
\t输出:
确定化的有穷状态自动机DFA\n\n"
\t姓名:
鲁庆河(E01214055)\n"
\t日期:
2015.05.12--2015.05.15\n"
getch();
b)截图: