这篇文章主要由三个C/C++代码和1个MATLAB代码构成,一方面用于我个人的知识记录,另一方面用于交流学习
一、网上代码修改版:
1、直接上代码:
代码参考于:A*算法(解决八数码问题)
#include
#define maxn 1010 //用于设置OPEN表和COLSE表(顺序表)结点的个数
#define N 3 //4
typedef struct node { //八数码结构体
int a[N][N]; //二维数组表示八数码的主要状态
int i_0, j_0; //空格的下标
int d, w, f; //搜索深度,各棋子不在正确位置的数目,总代价
struct node *father;//指向父节点指针
} node, *p_node;
typedef struct list { //顺序表结构体
p_node a[maxn]; //定义八数码结构体数组
int length; //记录当前顺序表中有多少结点
int cre_node_num; //生成结点的个数
} list, *p_list;
//预先定义好初始和目标八数码结点(可根据具体情况自己设置)
static int si[N][N] = {2,8,3,1,6,4,7,0,5}; //初始结点
//static int si[N][N] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0 };
static int sg[N][N] = {1,2,3,8,0,4,7,6,5}; //目标结点
//static int sg[N][N] = { 1,2,3,4,6,7,8,0,5,10,11,12,9,13,14,15 };
/* 初始八数码 目标八数码
2 8 3 1 2 3
1 6 4 8 0 4
7 0 5 7 6 5
*/
//给初始状态八数码和目标状态八数码结构体开辟空间
p_node s_i = (p_node)malloc(sizeof(node)); //初始节点
p_node s_g = (p_node)malloc(sizeof(node)); //目标节点
//给OPEN表和CLOSE表构体开辟空间
p_list OPEN = (p_list)malloc(sizeof(list)); //OPEN表
p_list CLOSE = (p_list)malloc(sizeof(list)); //CLOSE表
//声明函数
int w(p_node s); //1、启发函数(即h(x),可结合实际情况调整)
int f(p_node s); //2、估价函数
void init_node(); //3、初始化
void out_node(p_node s); //4、输出八数码
void list_reverse(p_node &p); //5、将链表逆序
void out_list(p_list &l,int num); //6、输出OPEN表
bool search_list(p_list &l, p_node s); //7、对表进行查找,成功返回true
void sort_list(p_list &l); //8、对OPEN表进行排序(按f从小到大)
void add_list(p_list &l, p_node s); //9、加入结点到OPEN表中或CLOSE表中
void copy_node(p_node s1, p_node &s2); //10、生成新的结点(将s2赋值给s1)
void delete_list(p_list &l); //11、从OPEN表或CLOSE中删除结点
bool is_equal(p_node s1, p_node s2); //12、判断两节点是否相等
bool up_mov(p_node &s); //13、空格上移
bool down_mov(p_node &s); //14、空格下移
bool left_mov(p_node &s); //15、空格左移
bool right_mov(p_node &s); //16、空格右移
void move(p_list &l,p_node s); //17、移动父节点并加入未探索表中(扩展结点)
int find_ij(int a,int flag); //18、找到目标函数函数对应的位置
int main()
{
init_node();//初始化
int num=1; //判断当前是第几次输出的OPEN表
printf("\nA*算法求解八数码问题求解过程如下:\n");
while (OPEN->length != 0 && CLOSE->length <maxn) { //循环到CLOSE->length>=maxn的时候退出
p_node n = OPEN->a[0]; //把Open表的第一个节点取出放入Close表,并记该节点为n
delete_list(OPEN); //将刚取出的第一个节点删除
CLOSE->cre_node_num++;
add_list(CLOSE, n);//将取出的结点加CLOSE表中
if (is_equal(n, s_g)) { //考察节点n是否为目标节点。若是,则找到了问题的解,成功退出;
list_reverse(n);
while (n) {
printf("第 %d 步:\n", n->d + 1);
out_node(n);
n = n->father;
}
printf("生成结点数:%d\n",OPEN->cre_node_num);
printf("扩展结点数:%d\n",CLOSE->cre_node_num-1);
break;
}
move(OPEN,n); //扩展节点
sort_list(OPEN); //OPEN表按照f值从小到大排序
out_list(OPEN,num++); //输出OPEN表
}
if (OPEN->length == 0) {
printf("\n从初始结点无法到达目标结点!\n\n");
}
return 0;
}
//启发函数1:曼哈顿距离
int w(p_node s)
{
int r = 0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
r += abs(i - find_ij(s->a[i][j],0)) + abs(j - find_ij(s->a[i][j],1));
}
}
return r;
}
//启发函数2:返回不在对应位置数字的个数
int w1(p_node s)
{
int r = 0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (s->a[i][j] != sg[i][j])
r++;
}
}
if (s->a[1][1] == sg[1][1])
r++;
return r-1;
}
int f(p_node s)
{
return (s->d + s->w );
}
//初始化开始状态和目标状态八数码结构体
void init_node()
{
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
s_i->a[i][j] = si[i][j];
if (s_i->a[i][j] == 0) {
s_i->i_0 = i;
s_i->j_0 = j;
}
}
}
s_i->d = 0;
s_i->w = w(s_i);
s_i->f = f(s_i);
s_i->father = NULL;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
s_g->a[i][j] = sg[i][j];
if (s_g->a[i][j] == 0) {
s_g->i_0 = i;
s_g->j_0 = j;
}
}
}
s_g->d = 0;
s_g->w = w(s_g);
s_g->f = f(s_g);
OPEN->length = 0;
CLOSE->length = 0;
OPEN->cre_node_num=0;
CLOSE->cre_node_num=0;
add_list(OPEN, s_i); //初始节点加入OPEN表中
printf("初始节点为:\n"); //打印初始节点
out_node(s_i);
printf("目标节点为:\n"); //打印目标节点
out_node(s_g);
}
//输出八数码
void out_node(p_node s)
{
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
printf("%d ", s->a[i][j]);
}
printf("\n");
}
printf("d=%d,f=%d\n", s->d, s->f);
}
//将链表逆序
void list_reverse(p_node & p)
{
p_node p_pre, p_suc;
p_pre = NULL;
p_suc = p->father;
while (p) {
p->father = p_pre;
p_pre = p;
if (p_suc == NULL)
break;
p = p_suc;
p_suc = p_suc->father;
}
}
//输出OPEN表
void out_list(p_list &l,int num)
{
printf("**********************第%d次输出OPEN表**************************\n",num);
for (int i = 0; i < l->length; i++) {
out_node(l->a[i]);
}
printf("**************************************************************\n");
}
//对表进行查找,成功返回true
bool search_list(p_list &l, p_node s)
{
for (int i = 0; i < l->length; i++) {
if (is_equal(l->a[i], s))
return true;
}
return false;
}
//对OPEN表进行排序(按f从小到大)(插入)
void sort_list(p_list &l)
{
p_node temp = (p_node)malloc(sizeof(node));
for (int i = 1; i < l->length; i++) {
int j = i - 1;
copy_node(temp, l->a[i]);
while (j >= 0 && (temp->f < l->a[j]->f)) {
copy_node(l->a[j + 1], l->a[j]);//l->a[j + 1] = l->a[j];
j--;
}
copy_node(l->a[j + 1], temp);
}
}
//加入结点到OPEN表中或CLOSE表中
void add_list(p_list & l, p_node s)
{
l->a[l->length++] = s;
}
//生成新的结点(将s2赋值给s1)
void copy_node(p_node s1, p_node &s2)
{
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
s1->a[i][j] = s2->a[i][j];
}
}
s1->i_0 = s2->i_0;
s1->j_0 = s2->j_0;
s1->d = s2->d;
s1->w = s2->w;
s1->f = s2->f;
s1->father = s2->father;
}
//从OPEN表或CLOSE中删除结点
void delete_list(p_list & l)
{
for (int i = 0; i < l->length; i++) {
l->a[i] = l->a[i + 1];
}
l->length--;
}
//判断两结点是否相等
bool is_equal(p_node s1, p_node s2)
{
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (s1->a[i][j] != s2->a[i][j]) {
return false;
}
}
}
return true;
}
//空格左移
bool left_mov(p_node &s)
{
if (s->j_0 == 0)
return false;
int temp;
temp = s->a[s->i_0][s->j_0];
s->a[s->i_0][s->j_0] = s->a[s->i_0][s->j_0 - 1];
s->a[s->i_0][s->j_0 - 1] = temp;
s->j_0--;
return true;
}
//空格右移
bool right_mov(p_node &s)
{
if (s->j_0 == N - 1)
return false;
int temp;
temp = s->a[s->i_0][s->j_0];
s->a[s->i_0][s->j_0] = s->a[s->i_0][s->j_0 + 1];
s->a[s->i_0][s->j_0 + 1] = temp;
s->j_0++;
return true;
}
//空格上移
bool up_mov(p_node &s)
{
if (s->i_0 == 0)
return false;
int temp;
temp = s->a[s->i_0][s->j_0];
s->a[s->i_0][s->j_0] = s->a[s->i_0 - 1][s->j_0];
s->a[s->i_0 - 1][s->j_0] = temp;
s->i_0--;
return true;
}
//空格下移
bool down_mov(p_node &s)
{
if (s->i_0 == N - 1)
return false;
int temp;
temp = s->a[s->i_0][s->j_0];
s->a[s->i_0][s->j_0] = s->a[s->i_0 + 1][s->j_0];
s->a[s->i_0 + 1][s->j_0] = temp;
s->i_0++;
return true;
}
//移动父节点并加入未探索表中(扩展结点)
void move(p_list &l,p_node s)
{
p_node p1 = (p_node)malloc(sizeof(node));
p_node p2 = (p_node)malloc(sizeof(node));
p_node p3 = (p_node)malloc(sizeof(node));
p_node p4 = (p_node)malloc(sizeof(node));
copy_node(p1, s);
copy_node(p2, s);
copy_node(p3, s);
copy_node(p4, s);
p1->father = s;
p2->father = s;
p3->father = s;
p4->father = s;
//如果能够移动且在CLOSE表中不存在,则加入OPEN表中
if (left_mov(p1) && !is_equal(p1, p1->father) && !search_list(CLOSE, p1) && !search_list(OPEN, p1)) {
p1->d++;
p1->w = w(p1);
p1->f = f(p1);
l->cre_node_num++;
add_list(OPEN, p1);
} else
free(p1);
if (right_mov(p2) && !is_equal(p2, p2->father) && !search_list(CLOSE, p2) && !search_list(OPEN, p2)) {
p2->d++;
p2->w = w(p2);
p2->f = f(p2);
l->cre_node_num++;
add_list(OPEN, p2);
} else
free(p2);
if (up_mov(p3) && !is_equal(p3, p3->father) && !search_list(CLOSE, p3) && !search_list(OPEN, p3)) {
p3->d++;
p3->w = w(p3);
p3->f = f(p3);
l->cre_node_num++;
add_list(OPEN, p3);
} else
free(p3);
if (down_mov(p4) && !is_equal(p4, p4->father) && !search_list(CLOSE, p4) && !search_list(OPEN, p4)) {
add_list(OPEN, p4);
p4->d++;
p4->w = w(p4);
p4->f = f(p4);
l->cre_node_num++;
} else
free(p4);
}
int find_ij(int a,int flag)
{
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (sg[i][j] == a)
if(flag==0)
return i;
else
return j;
}
}
}
2、部分运行结果
二、他山之石:简略版
这个代码给人的主要启发是:其实照着BFS(广度搜索)的思路直接敲完,核心框架也就出来了
#include
#include
using namespace std;
const int N=3;
int fl=0;//哪种
struct node{
int id,fval,gval,hval;
int faid,x,y;
int state[N][N];
friend bool operator<(node a,node b){
return a.fval>b.fval;
}
}st,ed;
int sta[N][N]={2,8,3,1,6,4,7,0,5};
int eda[N][N]={1,2,3,8,0,4,7,6,5};
//int sta[N][N]={0,1,2,3,4,5,6,7,8};
//int eda[N][N]={1,4,2,3,5,8,6,7,0};
int tar[N*N][2];
int idnum=0;
int nxt[4][2]={0,1,0,-1,1,0,-1,0};
int h(node a,int fl){
int num=0,id=1;
if(fl==0){//h(n)
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
// if(i==2&&j==2&&a.state[i][j]==0) continue;
if(a.state[i][j]!=eda[i][j])num++;
id++;
}
}
}
else{//p(n)
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
if(a.state[i][j]==0) continue;
int val=a.state[i][j];
num+=abs(i-tar[val][0])+abs(j-tar[val][1]);
}
}
}
return num;
}
void init(){
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
tar[eda[i][j]][0]=i;
tar[eda[i][j]][1]=j;
if(sta[i][j]==0) st.x=i,st.y=j;
st.state[i][j]=sta[i][j];
ed.state[i][j]=eda[i][j];
}
}
st.id=idnum++;
st.gval=0;
st.hval=h(st,fl);
st.fval=st.hval+st.gval;
st.faid=-1;
}
priority_queue<node> q;//q-open
vector<node> close;
map<string,int> mp,mq;//close open
void Astar(){
string ed1="";
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
ed1+=eda[i][j];
q.push(st);
string ss="";
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
ss+=sta[i][j];
}
}
mq[ss]=1;
while(!q.empty()){
node nn=q.top();
q.pop();
close.push_back(nn);
ss="";
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
ss+=nn.state[i][j];
}
}
if(ss==ed1){
break;
}
mq[ss]=0;
if(mp[ss]) continue;
mp[ss]=1;
for(int k=0;k<4;k++){
int tx=nn.x+nxt[k][0];
int ty=nn.y+nxt[k][1];
if(tx<0||ty<0||tx>=N||ty>=N)continue;
node tmp=nn;
swap(tmp.state[tx][ty],tmp.state[nn.x][nn.y]);
ss="";
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
ss+=tmp.state[i][j];
if(mq[ss]||mp[ss]) continue;
tmp.faid=tmp.id;
tmp.id=idnum++;
tmp.gval++;
tmp.x=tx;
tmp.y=ty;
tmp.hval=h(tmp,fl);
tmp.fval=tmp.gval+tmp.hval;
q.push(tmp);
}
}
}
void out(){
printf("一共扩展多少结点:%d\n",q.size()+close.size());
printf("从初始到目标经历多少结点:%d\n",close.size());
printf("扩展过程:\n");
for(int i=0;i<close.size();i++){
printf("第%d个结点为:\n",i+1);
for(int j=0;j<N;j++){
for(int k=0;k<N;k++)
printf("%d ",close[i].state[j][k]);
puts("");
}
}
}
int main()
{
int t,i,j,k;
init();
Astar();
out();
return 0;
}
三、不知道具体出处的代码,粘贴就完事了
1、五百多行的代码即将来袭:
#include
#include
#define size 3
using namespace std;
//定义二维数组来存储数据表示某一个特定状态
typedef int status[size][size];
struct SpringLink;
//定义状态图中的结点数据结构
typedef struct Node
{
status data;//结点所存储的状态
struct Node *parent;//指向结点的父亲结点
struct SpringLink *child;//指向结点的后继结点
struct Node *next;//指向open或者closed表中的后一个结点
int fvalue;//结点的总的路径
int gvalue;//结点的实际路径
int hvalue;//结点的到达目标的困难程度
}NNode , *PNode;
//定义存储指向结点后继结点的指针的地址
typedef struct SpringLink
{
struct Node *pointData;//指向结点的指针
struct SpringLink *next;//指向兄弟结点
}SPLink , *PSPLink;
PNode open;
PNode closed;
//开始状态与目标状态
status startt = {0,1,2,3,4,5,6,7,8};
status target = {1,4,2,3,5,8,6,7,0};
//初始化一个空链表
void initLink(PNode &Head)
{
Head = (PNode)malloc(sizeof(NNode));
Head->next = NULL;
}
//判断链表是否为空
bool isEmpty(PNode Head)
{
if(Head->next == NULL)
return true;
else
return false;
}
//从链表中拿出一个数据
void popNode(PNode &Head , PNode &FNode)
{
if(isEmpty(Head))
{
FNode = NULL;
return;
}
FNode = Head->next;
Head->next = Head->next->next;
FNode->next = NULL;
}
//向结点的最终后继结点链表中添加新的子结点
void addSpringNode(PNode &Head , PNode newData)
{
PSPLink newNode = (PSPLink)malloc(sizeof(SPLink));
newNode->pointData = newData;
newNode->next = Head->child;
Head->child = newNode;
}
//释放状态图中存放结点后继结点地址的空间
void freeSpringLink(PSPLink &Head)
{
PSPLink tmm;
while(Head != NULL)
{
tmm = Head;
Head = Head->next;
free(tmm);
}
}
//释放open表与closed表中的资源
void freeLink(PNode &Head)
{
PNode tmn;
tmn = Head;
Head = Head->next;
free(tmn);
while(Head != NULL)
{
//首先释放存放结点后继结点地址的空间
freeSpringLink(Head->child);
tmn = Head;
Head = Head->next;
free(tmn);
}
}
//向普通链表中添加一个结点
void addNode(PNode &Head , PNode &newNode)
{
newNode->next = Head->next;
Head->next = newNode;
}
//向非递减排列的链表中添加一个结点
void addAscNode(PNode &Head , PNode &newNode)
{
PNode P;
PNode Q;
P = Head->next;
Q = Head;
while(P != NULL && P->fvalue < newNode->fvalue)
{
Q = P;
P = P->next;
}
//上面判断好位置之后,下面就是简单的插入了
newNode->next = Q->next;
Q->next = newNode;
}
//计算结点额h值
int computeHValue(PNode theNode)
{
int num = 0;
for(int i = 0 ; i < 3 ; i++)
{
for(int j = 0 ; j < 3 ; j++)
{
if(theNode->data[i][j] != target[i][j])
num++;
}
}
return num;
}
//计算结点的f,g,h值
void computeAllValue(PNode &theNode , PNode parentNode)
{
if(parentNode == NULL)
theNode->gvalue = 0;
else
theNode->gvalue = parentNode->gvalue + 1;
theNode->hvalue = computeHValue(theNode);
theNode->fvalue = theNode->gvalue + theNode->hvalue;
}
//初始化函数,进行算法初始条件的设置
void initial()
{
//初始化open以及closed表
initLink(open);
initLink(closed);
//初始化起始结点,令初始结点的父节点为空结点
PNode NULLNode = NULL;
PNode Start = (PNode)malloc(sizeof(NNode));
for(int i = 0 ; i < 3 ; i++)
{
for(int j = 0 ; j < 3 ; j++)
{
Start->data[i][j] = startt[i][j];
}
}
Start->parent = NULL;
Start->child = NULL;
Start->next = NULL;
computeAllValue(Start , NULLNode);
//起始结点进入open表
addAscNode(open , Start);
}
//将B节点的状态赋值给A结点
void statusAEB(PNode &ANode , PNode BNode)
{
for(int i = 0 ; i < 3 ; i++)
{
for(int j = 0 ; j < 3 ; j++)
{
ANode->data[i][j] = BNode->data[i][j];
}
}
}
//两个结点是否有相同的状态
bool hasSameStatus(PNode ANode , PNode BNode)
{
for(int i = 0 ; i < 3 ; i++)
{
for(int j = 0 ; j < 3 ; j++)
{
if(ANode->data[i][j] != BNode->data[i][j])
return false;
}
}
return true;
}
//结点与其祖先结点是否有相同的状态
bool hasAnceSameStatus(PNode OrigiNode , PNode AnceNode)
{
while(AnceNode != NULL)
{
if(hasSameStatus(OrigiNode , AnceNode))
return true;
AnceNode = AnceNode->parent;
}
return false;
}
//取得方格中空的格子的位置
void getPosition(PNode theNode , int &row , int &col)
{
for(int i = 0 ; i < 3 ; i++)
{
for(int j = 0 ; j < 3 ; j++)
{
if(theNode->data[i][j] == 0)
{
row = i;
col = j;
return;
}
}
}
}
//交换两个数字的值
void changeAB(int &A , int &B)
{
int C;
C = B;
B = A;
A = C;
}
//检查相应的状态是否在某一个链表中
bool inLink(PNode spciNode , PNode theLink , PNode &theNodeLink , PNode &preNode)
{
preNode = theLink;
theLink = theLink->next;
while(theLink != NULL)
{
if(hasSameStatus(spciNode , theLink))
{
theNodeLink = theLink;
return true;
}
preNode = theLink;
theLink = theLink->next;
}
return false;
}
//产生结点的后继结点(与祖先状态不同)链表
void SpringLink(PNode theNode , PNode &spring)
{
int row;
int col;
getPosition(theNode , row , col);
//空的格子右边的格子向左移动
if(col != 2)
{
PNode rlNewNode = (PNode)malloc(sizeof(NNode));
statusAEB(rlNewNode , theNode);
changeAB(rlNewNode->data[row][col] , rlNewNode->data[row][col + 1]);
if(hasAnceSameStatus(rlNewNode , theNode->parent))
{
free(rlNewNode);//与父辈相同,丢弃本结点
}
else
{
rlNewNode->parent = theNode;
rlNewNode->child = NULL;
rlNewNode->next = NULL;
computeAllValue(rlNewNode , theNode);
//将本结点加入后继结点链表
addNode(spring , rlNewNode);
}
}
//空的格子左边的格子向右移动
if(col != 0)
{
PNode lrNewNode = (PNode)malloc(sizeof(NNode));
statusAEB(lrNewNode , theNode);
changeAB(lrNewNode->data[row][col] , lrNewNode->data[row][col - 1]);
if(hasAnceSameStatus(lrNewNode , theNode->parent))
{
free(lrNewNode);//与父辈相同,丢弃本结点
}
else
{
lrNewNode->parent = theNode;
lrNewNode->child = NULL;
lrNewNode->next = NULL;
computeAllValue(lrNewNode , theNode);
//将本结点加入后继结点链表
addNode(spring , lrNewNode);
}
}
//空的格子上边的格子向下移动
if(row != 0)
{
PNode udNewNode = (PNode)malloc(sizeof(NNode));
statusAEB(udNewNode , theNode);
changeAB(udNewNode->data[row][col] , udNewNode->data[row - 1][col]);
if(hasAnceSameStatus(udNewNode , theNode->parent))
{
free(udNewNode);//与父辈相同,丢弃本结点
}
else
{
udNewNode->parent = theNode;
udNewNode->child = NULL;
udNewNode->next = NULL;
computeAllValue(udNewNode , theNode);
//将本结点加入后继结点链表
addNode(spring , udNewNode);
}
}
//空的格子下边的格子向上移动
if(row != 2)
{
PNode duNewNode = (PNode)malloc(sizeof(NNode));
statusAEB(duNewNode , theNode);
changeAB(duNewNode->data[row][col] , duNewNode->data[row + 1][col]);
if(hasAnceSameStatus(duNewNode , theNode->parent))
{
free(duNewNode);//与父辈相同,丢弃本结点
}
else
{
duNewNode->parent = theNode;
duNewNode->child = NULL;
duNewNode->next = NULL;
computeAllValue(duNewNode , theNode);
//将本结点加入后继结点链表
addNode(spring , duNewNode);
}
}
}
//输出给定结点的状态
void outputStatus(PNode stat)
{
for(int i = 0 ; i < 3 ; i++)
{
for(int j = 0 ; j < 3 ; j++)
{
cout << stat->data[i][j] << " ";
}
cout << endl;
}
}
//输出最佳的路径
void outputBestRoad(PNode goal)
{
int deepnum = goal->gvalue;
if(goal->parent != NULL)
{
outputBestRoad(goal->parent);
}
cout << "第" << deepnum-- << "层的状态:" << endl;
outputStatus(goal);
}
void AStar()
{
PNode tmpNode;//指向从open表中拿出并放到closed表中的结点的指针
PNode spring;//tmpNode的后继结点链
PNode tmpLNode;//tmpNode的某一个后继结点
PNode tmpChartNode;
PNode thePreNode;//指向将要从closed表中移到open表中的结点的前一个结点的指针
bool getGoal = false;//标识是否达到目标状态
long numcount = 1;//记录从open表中拿出结点的序号
initial();//对函数进行初始化
initLink(spring);//对后继链表的初始化
tmpChartNode = NULL;
cout << "从open表中拿出的结点的状态及相应的值" << endl;
while(!isEmpty(open))
{
//从open表中拿出f值最小的元素,并将拿出的元素放入closed表中
popNode(open , tmpNode);
addNode(closed , tmpNode);
cout << "第" << numcount++ << "个状态是:" << endl;
outputStatus(tmpNode);
cout << "其f值为:" << tmpNode->fvalue << endl;
cout << "其g值为:" << tmpNode->gvalue << endl;
cout << "其h值为:" << tmpNode->hvalue << endl;
//如果拿出的元素是目标状态则跳出循环
if(computeHValue(tmpNode) == 0)
{
getGoal = true;
break;
}
//产生当前检测结点的后继(与祖先不同)结点列表,产生的后继结点的parent属性指向当前检测的结点
SpringLink(tmpNode , spring);
//遍历检测结点的后继结点链表
while(!isEmpty(spring))
{
popNode(spring , tmpLNode);
//状态在open表中已经存在,thePreNode参数在这里并不起作用
if(inLink(tmpLNode , open , tmpChartNode , thePreNode))
{
addSpringNode(tmpNode , tmpChartNode);
if(tmpLNode->gvalue < tmpChartNode->gvalue)
{
tmpChartNode->parent = tmpLNode->parent;
tmpChartNode->gvalue = tmpLNode->gvalue;
tmpChartNode->fvalue = tmpLNode->fvalue;
}
free(tmpLNode);
}
//状态在closed表中已经存在
else if(inLink(tmpLNode , closed , tmpChartNode , thePreNode))
{
addSpringNode(tmpNode , tmpChartNode);
if(tmpLNode->gvalue < tmpChartNode->gvalue)
{
PNode commu;
tmpChartNode->parent = tmpLNode->parent;
tmpChartNode->gvalue = tmpLNode->gvalue;
tmpChartNode->fvalue = tmpLNode->fvalue;
freeSpringLink(tmpChartNode->child);
tmpChartNode->child = NULL;
popNode(thePreNode , commu);
addAscNode(open , commu);
}
free(tmpLNode);
}
//新的状态即此状态既不在open表中也不在closed表中
else
{
addSpringNode(tmpNode , tmpLNode);
addAscNode(open , tmpLNode);
}
}
}
//目标可达的话,输出最佳的路径
if(getGoal)
{
cout << endl;
cout << "最佳路径长度为:" << tmpNode->gvalue << endl;
cout << "最佳路径为:" <<endl;
outputBestRoad(tmpNode);
}
//释放结点所占的内存
freeLink(open);
freeLink(closed);
getchar();
}
int main()
{
AStar();
return 0;
}
四、MATLBA"实现"
%八数码A*算法程序
function [a1,b1]=shang(a)
[x,y]=find(a==0);
a1=a;
a1(x,y)=a(x-1,y);
a1(x-1,y)=0;
b1=zhao(a1);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [a1,b1]=xia(a)
[x,y]=find(a==0);
a1=a;
a1(x,y)=a(x+1,y);
a1(x+1,y)=0;
b1=zhao(a1);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [a1,b1]=zuo(a)
[x,y]=find(a==0);
a1=a;
a1(x,y)=a(x,y-1);
a1(x,y-1)=0;
b1=zhao(a1);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [a1,b1]=you(a)
[x,y]=find(a==0);
a1=a;
a1(x,y)=a(x,y+1);
a1(x,y+1)=0;
b1=zhao(a1);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function z=panduan(a)
global E;
global I;
I=2;
[x,y]=size(E);
z=1;
for i=1:y
b=E{i};
v=(b-a).^2;
if sum(sum(v))==0
z=0;
break;
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function y=zhao(a)
wan=[1 2 3;8 0 4;7 6 5];
y=0;
b=a-wan;
for i=1:3
for j=1:3
if b(i,j)~=0
y=y+1;
end
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
global E
global I
a=[2 8 3;1 0 4;7 6 5];
b=[1 2 3;8 0 4;7 6 5];
I=1;
E(1)={a};
for i=2:20
q=b-E{i};
if sum(sum(q.^2))
E(i)={kaka(E{i-1})};
celldisp(E(i))
else
break;
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [a1]=kaka(a)
global I;
global E;
c=[2 8 3;1 0 4;7 6 5];
E(1)={c};
[x,y]=find(a==0);
z=9;
if x==1
if y==1
[x1,y1]=xia(a);
if y1<z
if panduan(x1)
b=x1;
z=y1;
end
end
[x2,y2]=you(a);
if y2<z
if panduan(x2)
b=x2;
z=y2;
end
end
a1=b;
end
if y==2
[x1,y1]=xia(a);
if y1<z
if panduan(x1)
b=x1;
z=y1;
end
end
[x2,y2]=zuo(a);
if y2<z
if panduan(x2)
b=x2;
z=y2;
end
end
[x3,y3]=you(a);
if y3<z
if panduan(x3)
b=x3;
z=y3;
end
end
a1=b;
end
if y==3
[x1,y1]=xia(a);
if y1<z
if panduan(x1)
b=x1;
z=y1;
end
end
[x2,y2]=zuo(a);
if y2<z
if panduan(x2)
b=x2;
z=y2;
end
end
a1=b;
end
end
if x==2
if y==1
[x1,y1]=shang(a);
if y1<z
if panduan(x1)
b=x1;
z=y1;
end
end
[x2,y2]=xia(a);
if y2<z
if panduan(x2)
b=x2;
z=y2;
end
end
[x3,y3]=you(a);
if y3<z
if panduan(x3)
b=x3;
z=y3;
end
end
a1=b;
end
if y==2
[x1,y1]=shang(a);
if y1<z
if panduan(x1);
b=x1;
z=y1;
end
end
[x2,y2]=xia(a);
if y2<z
if panduan(x2);
b=x2;
z=y2;
end
end
[x3,y3]=zuo(a);
if y3<z
if panduan(x3);
b=x3;
z=y3;
end
end
[x4,y4]=you(a);
if y4<z;
if panduan(x4)
b=x4;
z=y4;
end
end
a1=b;
end
if y==3
[x1,y1]=shang(a);
if y1<z
if panduan(x1)
b=x1;
z=y1;
end
end
[x2,y2]=xia(a);
if y2<z
if panduan(x2)
b=x2;
z=y2;
end
end
[x3,y3]=zuo(a);
if y3<z
if panduan(x3)
b=x3;
z=y3;
end
end
a1=b;
end
end
if x==3
if y==1
[x1,y1]=shang(a);
if y1<z
if panduan(x1)
b=x1;
z=y1;
end
end
[x4,y4]=you(a);
if y4<z;
if panduan(x4)
b=x4;
z=y4;
end
end
a1=b;
end
if y==2
[x1,y1]=shang(a);
if y1<z
if panduan(x1)
b=x1;
z=y1;
end
end
[x3,y3]=zuo(a);
if y3<z
if panduan(x3)
b=x3;
z=y3;
end
end
[x4,y4]=you(a);
if y4<z;
if panduan(x4)
b=x4;
z=y4;
end
end
a1=b;
end
if y==3
[x1,y1]=shang(a);
if y1<z
if panduan(x1)
b=x1;
z=y1;
end
end
[x3,y3]=zuo(a);
if y3<z
if panduan(x3)
b=x3;
z=y3;
end
end
a1=b;
end
end
E(I)={a1};