A*算法实验

本文由用户“情碎必”分享发布 更新时间:2021-11-02 05:34:05 举报文档

以下为《A*算法实验》的无排版文字预览,完整格式请下载

下载前请仔细阅读文字预览以及下方图片预览。图片预览是什么样的,下载的文档就是什么样的。

熟悉和掌握启发式搜索的定义、估价函数和算法过程,并利用A*算法求解N数码难题,理解求解流程和搜索顺序。

二、实验原理:

A*算法是一种启发式图搜索算法,其特点在于对估价函数的定义上。对于一般的启发式图搜索,总是选择估价函数f值最小的节点作为扩展节点。因此,f是根据需要找到一条最小代价路径的观点来估算节点的,所以,可考虑每个节点n的估价函数值为两个分量:从起始节点到节点n的实际代价以及从节点n到达目标节点的估价代价。三、 主要仪器设备、试剂或材料

三、实验内容:

1.参考A*算法核心代码,以8数码问题为例实现A*算法的求解程序(编程语言不限),要求设计两种不同的估价函数。

2.在求解8数码问题的A*算法程序中,设置相同的初始状态和目标状态,针对不同的估价函数,求得问题的解,并比较它们对搜索算法性能的影响,包括扩展节点数、生成节点数等。

3.对于8数码问题,设置与上述2相同的初始状态和目标状态,用宽度优先搜索算法(即令估计代价h(n)=0的A*算法)求得问题的解,以及搜索过程中的扩展节点数、生成节点数。

4.上交源程序。

四.源代码与实验截图

#include

#include

#include

//八数码状态对应的节点结构体

struct Node{

int s[3][3];//保存八数码状态,0代表空格

int f,g;//启发函数中的f和g值

struct Node * next;

struct Node *previous;//保存其父节点

};

int open_N=0; //记录Open列表中节点数目

//八数码初始状态

int inital_s[3][3]={

2,8,3,

1,6,4,

7,0,5

};

//八数码目标状态

int final_s[3][3]={

1,2,3,

8,0,4,

7,6,5

};

//------------------------------------------------------------------------

//添加节点函数入口,方法:通过插入排序向指定表添加

//------------------------------------------------------------------------

void Add_Node( struct Node *head, struct Node *p)

{

struct Node *q;

if(head->next)//考虑链表为空

{ q = head->next;

if(p->f < head->next->f){//考虑插入的节点值比链表的第一个节点值小

p->next = head->next;

head->next = p;

}

else {

while(q->next)//考虑插入节点x,形如af ||q->f == p->f) && (q->next->f > p->f || q->next->f == p->f)){

p->next = q->next;

q->next = p;

break;

}

q = q->next;

}

if(q->next == NULL) //考虑插入的节点值比链表最后一个元素的值更大

q->next = p;

}

}

else head->next = p;

}

//------------------------------------------------------------------------

//删除节点函数入口

//------------------------------------------------------------------------

void del_Node(struct Node * head, struct Node *p )

{

struct Node *q;

q = head;

while(q->next)

{

if(q->next == p){

q->next = p->next;

p->next = NULL;

if(q->next == NULL) return;

// free(p);

}

q = q->next;

}

}

//------------------------------------------------------------------------

//判断两个数组是否相等函数入口

//------------------------------------------------------------------------

int equal(int s1[3][3], int s2[3][3])

{

int i,j,flag=0;

for(i=0; i< 3 ; i++)

for(j=0; j< 3 ;j++)

if(s1[i][j] != s2[i][j]){flag = 1; break;}

if(!flag)

return 1;

else return 0;

}

//------------------------------------------------------------------------

//判断后继节点是否存在于Open或Closed表中函数入口

//------------------------------------------------------------------------

int exit_Node(struct Node * head,int s[3][3], struct Node *Old_Node)

{

struct Node *q=head->next;

int flag = 0;

while(q)

if(equal(q->s,s)) {

flag=1;

Old_Node->next = q;

return 1;}

else q = q->next;

if(!flag) return 0;

}

//------------------------------------------------------------------------

//计算p(n)的函数入口

//其中p(n)为放错位的数码与其正确的位置之间距离之和

//具体方法:放错位的数码与其正确的位置对应下标差的绝对值之和

//------------------------------------------------------------------------

int wrong_sum(int s[3][3])

{

int i,j,fi,fj,sum=0;

for(i=0 ; is[i_0-1][j_0] = temp;

return 1;

}

else return 0;

case 1: if((j_0-1)>-1){

temp = Successor->s[i_0][j_0];

Successor->s[i_0][j_0] = Successor->s[i_0][j_0-1];

Successor->s[i_0][j_0-1] = temp;

return 1;

}

else return 0;

case 2: if( (j_0+1)s[i_0][j_0];

Successor->s[i_0][j_0] = Successor->s[i_0][j_0+1];

Successor->s[i_0][j_0+1] = temp;

return 1;

}

else return 0;

case 3: if((i_0+1)s[i_0][j_0];

Successor->s[i_0][j_0] = Successor->s[i_0+1][j_0];

Successor->s[i_0+1][j_0] = temp;

return 1;

}

else return 0;

}

}

//------------------------------------------------------------------------

//从OPen表获取最佳节点函数入口

//------------------------------------------------------------------------

struct Node * get_BESTNODE(struct Node *Open)

{

return Open->next;

}

//------------------------------------------------------------------------

//输出最佳路径函数入口

//------------------------------------------------------------------------

void print_Path(struct Node * head)

{

struct Node *q, *q1,*p;

int i,j,count=1;

p = (struct Node *)malloc(sizeof(struct Node));

//通过头插法变更节点输出次序

p->previous = NULL;

q = head;

while(q)

{

q1 = q->previous;

q->previous = p->previous;

p->previous = q;

q = q1;

}

q = p->previous;

while(q)

{

if(q == p->previous)printf("八数码的初始状态:\n");

else if(q->previous == NULL)printf("八数码的目标状态:\n");

else printf("八数码的中间态%d\n",count++);

for(i=0; if,q->g);

q = q->previous;

}

}

//------------------------------------------------------------------------

//A*子算法入口:处理后继结点

//------------------------------------------------------------------------

void sub_A_algorithm(struct Node * Open, struct Node * BESTNODE, struct Node * Closed,struct Node *Successor)

{

struct Node * Old_Node = (struct Node *)malloc(sizeof(struct Node));

Successor->previous = BESTNODE;//建立从successor返回BESTNODE的指针

Successor->g = BESTNODE->g + 1;//计算后继结点的g值

//检查后继结点是否已存在于Open和Closed表中,如果存在:该节点记为old_Node,比较后继结点的g值和表中old_Node节点

//g值,前者小代表新的路径比老路径更好,将Old_Node的父节点改为BESTNODE,并修改其f,g值,后者小则什么也不做。

//即不存在Open也不存在Closed表则将其加入OPen表,并计算其f值

if( exit_Node(Open, Successor->s, Old_Node) ){

if(Successor->g < Old_Node->g){

Old_Node->next->previous = BESTNODE;//将Old_Node的父节点改为BESTNODE

Old_Node->next->g = Successor->g;//修改g值

Old_Node->next->f = Old_Node->g + wrong_sum(Old_Node->s);//修改f值

//排序~~~~~~~~~~~~~~~~~~

del_Node(Open, Old_Node);

Add_Node(Open, Old_Node);

}

}

else if( exit_Node(Closed, Successor->s, Old_Node)){

if(Successor->g < Old_Node->g){

Old_Node->next->previous = BESTNODE;

Old_Node->next->g = Successor->g;

Old_Node->next->f = Old_Node->g + wrong_sum(Old_Node->s);

//排序~~~~~~~~~~~~~~~~~~

del_Node(Closed, Old_Node);

Add_Node(Closed, Old_Node);

}

}

else {

Successor->f = Successor->g + wrong_sum(Successor->s);

Add_Node(Open, Successor);

open_N++;

}

}

//------------------------------------------------------------------------

//A*算法入口

//八数码问题的启发函数为:f(n)=d(n)+p(n)

//其中A*算法中的g(n)根据具体情况设计为d(n),意为n节点的深度,而h(n)设计为p(n),

//意为放错的数码与正确的位置距离之和

//------------------------------------------------------------------------

void A_algorithm(struct Node * Open, struct Node * Closed) //A*算法

{

int i,j;

struct Node * BESTNODE, *inital, * Successor;

inital = (struct Node * )malloc(sizeof(struct Node));

//初始化起始节点

for(i=0; if = wrong_sum(inital_s);

inital->g = 0;

inital->previous = NULL;

inital->next = NULL;

Add_Node(Open, inital);//把初始节点放入OPEN表

open_N++;

while(1)

{

if(open_N == 0){printf("failure!"); return;}

else {

BESTNODE = get_BESTNODE(Open);//从OPEN表获取f值最小的BESTNODE,将其从OPEN表删除并加入CLOSED表中

del_Node(Open, BESTNODE);

open_N--;

Add_Node(Closed, BESTNODE);

if(equal(BESTNODE->s, final_s)) {//判断 内容过长,仅展示头部和尾部部分文字预览,全文请查看图片预览。 }

}

//------------------------------------------------------------------------

//main()函数入口

//定义Open和Closed列表。Open列表:保存待检查节点。Closed列表:保存不需要再检查的节点

//------------------------------------------------------------------------

int main()

{

struct Node * Open = (struct Node * )malloc(sizeof(struct Node));

struct Node * Closed = (struct Node * )malloc(sizeof(struct Node));

Open->next = NULL ; Open->previous = NULL;

Closed->next =NULL; Closed->previous = NULL;

A_algorithm(Open, Closed);

}



[文章尾部最后500字内容到此结束,中间部分内容请查看底下的图片预览]

以上为《A*算法实验》的无排版文字预览,完整格式请下载

下载前请仔细阅读上面文字预览以及下方图片预览。图片预览是什么样的,下载的文档就是什么样的。

图片预览