1、八数码问题C代码*本函数是用A*算法来实现八数码的问题*算法的步骤如下:*1、初始化两个链表open和closed,将初始状态放入open表中*2、重复下列过程,直至找到目标结点为止,如果open表为空,那* 么查找失败;*3、从open表中拿出具有最小f值的结点(将这一结点称为BESTNODE),* 并放入closed表中;*4、如果BESTNODE为目标结点,成功求得解,退出循环;*5、如果BESTNODE不是目标结点,那么产生它的后继结点(此后继结* 点与其祖先的状态不同),后继结点组成一个链表;*6、对每个后继结点进行以下过程:*7、建立它到BESTNODE的parent指针;*8、如
2、果此结点在open表中,首先将open表中的结点添加进BESTNODE* 的后继结点链中,然后计算两个结点的g值,如果此结点的g值小* 于open表中的结点时,open表中的结点改变parent指针,同时将* 此结点删除;*9、如果此结点在closed表中,首先将closed表中的结点添加进BESTNODE* 的后继结点中,然后计算两个结点的g值,如果此结点的g值小于* closed表中的结点时,closed表中的结点改变parent指针;将* closed表中的结点重新放入open表中,同时将此结点删除;*10、如果此结点既不在open表中也不再closed表中,那么添加此结点至* BEST
3、NODE的后继结点链中。*Author: 转载 作者不详。*2011.5.16*/#include stdafx.h#include #include #include #define size 3using namespace std;/定义二维数组来存储数据表示某一个特定状态typedef int statussizesize;struct SpringLink;/定义状态图中的结点数据结构typedef struct Nodestatus data;/结点所存储的状态 Node *parent;/指向结点的父亲结点SpringLink *child;/指向结点的后继结点int fvalu
4、e;/结点的总的路径int gvalue;/结点的实际路径int hvalue;/结点的到达目标的苦难程度 Node *next;/指向open或者closed表中的后一个结点NNode , *PNode;/定义存储指向结点后继结点的指针的地址typedef struct SpringLinkNode *pointData;/指向结点的指针SpringLink *next;/指向兄第结点SPLink , *PSPLink;/定义open表和close表PNode open;PNode closed;/开始状态与目标状态status startt = 2 , 8 , 3 , 1 , 6 , 4
5、, 7 , 0 , 5;status target = 1 , 2 , 3 , 8 , 0 , 4 , 7 , 6 , 5;/初始化一个空链表void initLink(PNode &Head)Head = (PNode)malloc(sizeof(NNode);Head-next = NULL;/判断链表是否为空bool isEmpty(PNode Head)if(Head-next = NULL)return true;elsereturn false;/从链表中拿出一个数据,通过FNode返回void popNode(PNode &Head , PNode &FNode)if(isEmp
6、ty(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;/释放状态图中存放结点后继结点
7、地址的空间/注意传入参数PSPLink引用类型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
8、= 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 fvalue)Q = P;P = P-next;/上面判断好位置之后,下面就是简单的插入了newNo
9、de-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 dataij != targetij)num+;return num;/计算结点的f,g,h值void computeAllValue(PNode &theNode , PNode parentNode)if(parentNode = NULL)theNode-gvalue = 0;elsetheNode-g
10、value = 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
11、; i 3 ; i+)for(int j = 0 ; j dataij = starttij;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 dataij = BNode-dataij;/两个结
12、点是否有相同的状态bool hasSameStatus(PNode ANode , PNode BNode)for(int i = 0 ; i 3 ; i+)for(int j = 0 ; j dataij != BNode-dataij)return false;return true;/结点与其祖先结点是否有相同的状态bool hasAnceSameStatus(PNode OrigiNode , PNode AnceNode)while(AnceNode != NULL)if(hasSameStatus(OrigiNode , AnceNode)return true;AnceNode
13、= AnceNode-parent;return false;/取得方格中空的格子的位置,通过row,col返回。void getPosition(PNode theNode , int &row , int &col)for(int i = 0 ; i 3 ; i+)for(int j = 0 ; j dataij = 0)row = i;col = j;return;/交换两个数字的值void changeAB(int &A , int &B)int C;C = B;B = A;A = C;/检查相应的状态是否在某一个链表中,判断spciNode所指的节点是否在theLink所指的链表中。
14、/theNodeLink返回在链表中与spciNode状态相同的节点指针,preNode指向相同节点前驱。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 = theLi
15、nk-next;return false;/产生结点的后继结点(与祖先状态不同)链表/通过spring参数返回节点的后继节点链表void GenerateSpringLink(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-datarowcol
16、, rlNewNode-datarowcol + 1);if(hasAnceSameStatus(rlNewNode , theNode-parent)free(rlNewNode);/与父辈相同,丢弃本结点elserlNewNode-parent = theNode;rlNewNode-child = NULL;rlNewNode-next = NULL;computeAllValue(rlNewNode , theNode);/将本结点加入后继结点链表addNode(spring , rlNewNode);/空的格子左边的格子向右移动if(col != 0)PNode lrNewNode
17、= (PNode)malloc(sizeof(NNode);statusAEB(lrNewNode , theNode);changeAB(lrNewNode-datarowcol , lrNewNode-datarowcol - 1);if(hasAnceSameStatus(lrNewNode , theNode-parent)free(lrNewNode);/与父辈相同,丢弃本结点elselrNewNode-parent = theNode;lrNewNode-child = NULL;lrNewNode-next = NULL;computeAllValue(lrNewNode , t
18、heNode);/将本结点加入后继结点链表addNode(spring , lrNewNode);/空的格子上边的格子向下移动if(row != 0)PNode udNewNode = (PNode)malloc(sizeof(NNode);statusAEB(udNewNode , theNode);changeAB(udNewNode-datarowcol , udNewNode-datarow - 1col);if(hasAnceSameStatus(udNewNode , theNode-parent)free(udNewNode);/与父辈相同,丢弃本结点elseudNewNode-
19、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-datarowcol , duNewNode-datarow + 1col)
20、;if(hasAnceSameStatus(duNewNode , theNode-parent)free(duNewNode);/与父辈相同,丢弃本结点elseduNewNode-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(i
21、nt j = 0 ; j 3 ; j+)cout dataij ;cout 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;/指向将要从clo
22、sed表中移到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 第
23、 numcount+ 个状态是: endl;outputStatus(tmpNode);cout 其f值为: fvalue endl;cout 其g值为: gvalue endl;cout 其h值为: hvalue gvalue gvalue) /等价于if(tmpLNode-fvalue fvalue) tmpChartNode-parent = tmpLNode-parent;tmpChartNode-gvalue = tmpLNode-gvalue;tmpChartNode-fvalue = tmpLNode-fvalue;free(tmpLNode);/状态在closed表中已经存在else if(inLink(tmpLNode , closed , tmpChartNode , thePreNode) /此时他们hvalue值一样addSpringNode(tmpNode , tmpChartNode);if(tmpLNode-gvalue gvalue)PNode commu;tmpChartNode-parent = tmpLNode-parent;tmpChartNode-gvalue = tmpLNode-gvalue;tmpChartNode-fvalue = tmpLNode-fvalue;freeSpringL
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1