1、程序源代码
#include
#include
struct node{
int a[3][3];//用二维数组存放 8 数码
int hx;//函数 h(x)的值,表示与目标状态的差距
struct node *parent;//指向父结点的指针
struct node *next;//指向链表中下一个结点的指针
};
//------------------hx 函数-------------------//
int hx(int s[3][3])
{//函数说明:计算 s 与目标状态的差距值
int i,j;
int hx=0;
int sg[3][3]={1,2,3,8,0,4,7,6,5};
for(i=0;i<3;i++)
for(j=0;j<3;j++)
if(s[i][j]!=sg[i][j])
hx++;
return hx;
}
//-------------hx 函数 end----------------------//
//-------------extend 扩展函数----------------//
struct node *extend(node *ex)
{ //函数说明:扩展 ex 指向的结点,并将扩展所得结点组成一条
//单链表,head 指向该链表首结点,并且作为返回值
//临时替换变量
int i,j,m,n; //循环变量
int t;
int flag=0;
int x[3][3];//临时存放二维数组
struct node *p,*q,*head;
head=(node *)malloc(sizeof(node));//head
p=head;
q=head;
head->next=NULL;//初始化
for(i=0;i<3;i++)//找到二维数组中 0 的位置
{
for(j=0;j<3;j++)
if(ex->a[i][j]==0)
{
flag=1;
break;
}
if(flag==1)
break;
}
for(m=0;m<3;m++)//将 ex->a 赋给 x
for(n=0;n<3;n++)
x[m][n]=ex->a[m][n];
//根据 0 的位置的不同,对 x 进行相应的变换
//情况 1
if(i-1>=0)
{
t=x[i][j];x[i][j]=x[i-1][j];x[i-1][j]=t;
flag=0;
for(m=0;m<3;m++)//将 x 赋给 a
for(n=0;n<3;n++)
if(x[m][n]==ex->parent->a[m][n])
flag++;
if(flag!=9)
{
q=(node *)malloc(sizeof(node));
for(m=0;m<3;m++)//将 x 赋给 a
for(n=0;n<3;n++)
q->a[m][n]=x[m][n];
q->parent=ex;
q->hx=hx(q->a);
q->next=NULL;
p->next=q;
p=p->next;
}
}
//情况 2
for(m=0;m<3;m++)//将 ex->a 重新赋给 x,即还原 x
for(n=0;n<3;n++)
x[m][n]=ex->a[m][n];
if(i+1<=2)
{
t=x[i][j];x[i][j]=x[i+1][j];x[i+1][j]=t;
flag=0;
for(m=0;m<3;m++)
for(n=0;n<3;n++)
if(x[m][n]==ex->parent->a[m][n])
flag++;
if(flag!=9)
{
q=(node *)malloc(sizeof(node));
for(m=0;m<3;m++)//将 x 赋给 a
for(n=0;n<3;n++)
q->a[m][n]=x[m][n];
q->parent=ex;
q->hx=hx(q->a);
q->next=NULL;
p->next=q;
p=p->next;
}
}
//情况 3
for(m=0;m<3;m++)//将 ex->a 重新赋给 x,即还原 x
for(n=0;n<3;n++)
x[m][n]=ex->a[m][n];
if(j-1>=0)
{
t=x[i][j];x[i][j]=x[i][j-1];x[i][j-1]=t;
flag=0;
for(m=0;m<3;m++)
for(n=0;n<3;n++)
if(x[m][n]==ex->parent->a[m][n])
flag++;
if(flag!=9)
{
q=(node *)malloc(sizeof(node));
for(m=0;m<3;m++)//将 x 赋给 a
for(n=0;n<3;n++)
q->a[m][n]=x[m][n];
q->parent=ex;
q->hx=hx(q->a);
q->next=NULL;
p->next=q;
p=p->next;
}
}
//情况 4
for(m=0;m<3;m++)//将 ex->a 重新赋给 x,即还原 x
for(n=0;n<3;n++)
x[m][n]=ex->a[m][n];
if(j+1<=2)
{
t=x[i][j];x[i][j]=x[i][j+1];x[i][j+1]=t;
flag=0;
for(m=0;m<3;m++)
for(n=0;n<3;n++)
if(x[m][n]==ex->parent->a[m][n])
flag++;
if(flag!=9)
{
q=(node *)malloc(sizeof(node));
for(m=0;m<3;m++)
for(n=0;n<3;n++)
q->a[m][n]=x[m][n];
q->parent=ex;
q->hx=hx(q->a);
q->next=NULL;
p->next=q;
p=p->next;
}
}
head=head->next;
return head;
}
//---------------extend 函数 end-----------------------//
//----------------insert 函数-------------------------//
node* insert(node *open,node * head)
{ //函数说明:将 head 链表的结点依次插入到 open 链表相应的位置,
//使 open 表中的结点按从小到大排序。函数返回 open 指针
node *p,*q;//p、q 均指向 open 表中的结点,p 指向 q 所指的前一个结点
int i,j;
int flag=0;
if(open==NULL)//初始状态,open 表为空
{ //首先将 head 表第一个结点直接放入 open 表中
open=head;
q=head;
head=head->next;
q->next=NULL;
//再插入第二个结点
if(head->hxhx)
{//插入到首结点位置
open=head;
head=head->next;
open->next=q;
}
else
{ //或者第二个结点的位置
q->next=head;
head=head->next;
q=q->next;
q->next=NULL;
p=open;
}
p=open;
q=open->next;
} //end if
while(head!=NULL)
{
q=open;
if(head->hxhx) //插入到表头
{
open=head;
head=head->next;
open->next=q;
continue;
}
else { q=q->next;p=open;} //否则,q 指像第二个结点,p 指向 q 前一个结点
while(q->next!=NULL) //将 head 的一个结点插入到链表中(非表尾的位置)
{
if(q->hxhx)
{
q=q->next;
p=p->next;
}
else
{
p->next=head;
head=head->next;
p->next->next=q;
break;
}
}
if(q->next==NULL)//将 head 的一个结点插入到表尾
{
if(q->hx>head->hx)
{
p->next=head;
head=head->next;
p->next->next=q;
q->next=head;
head=head->next;
q->next->next=NULL;
}
else
{
}
}//if
}//while
return open;
}//insert
//-----------------insert 函数 end--------------------//
//---------------------main-----------------------//
void main()
{
int i,j;
node s0;
node *open,*close;
node *p,*q;
node *newlist;
printf("请输入初始状态的 8 数码(按每行从左往右依次输入,用 0 表示空格):\n");
for(i=0;i<3;i++)
for(j=0;j<3;j++)
scanf("%d",&s0.a[i][j]);
s0.parent=(node *)malloc(sizeof(node));
s0.parent->hx=9;
s0.hx=hx(s0.a);
open=&s0;
p=&s0;
if(open->hx==0)
{
printf("该状态已为最终状态!\n");
return;
}
q=&s0;
close=&s0;
open=NULL;
newlist=extend(q);//newlist 指向新扩展出来的链表
open=insert(open,newlist);//将扩展出来的结点插入到 open 表中
while(1)
{
q->next=open;//q 始终指向 close 表尾结点。将 open 表的第一个元素加到 close 表
open=open->next;
q=q->next;
q->next=NULL;
if(q->hx==0)
{
printf("\n 搜索成功!\n");
break;
}
newlist=extend(q);//对 close 表最后一个结点进行扩展,扩展得到的链表接到 open
open=insert(open,newlist);//将扩展的结点按顺序插入到 open 表中
表尾
}
p=close;
printf("择优搜索过程如下:\n");
while(p!=NULL)
{
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
printf("%d ",p->a[i][j]);
printf("\n");
}
printf("\n");
p=p->next;
}
}
2、程序运行结果截图
截图 1:
初始态为:
2
1
7
运行结果如
右图所示:
3
4
5
8
6