-回溯算法
回溯算法是递归算法的一种特殊形式。回溯算法的基本思想是:对一个包括有很多个结点,每个结点有若干个搜索分支的问题,把原问题分解为对若干个子问题求解的算法;当搜索到某个结点、发现无法再继续搜索下去时,就让搜索过程回溯(即退回)到该结点的前一结点,继续搜索这个结点的其他尚未搜索过的分支;如果发现这个结点也无法再继续搜索下去时,就让搜索过程回溯到这个结点的前一结点继续这样的搜索过程;这样的搜索过程一直进行到搜索到问题的解或搜索完了全部可搜索分支没有解存在为止。由于回溯算法每前进一步,在新的结点上进行的搜索过程和前一个结点的搜索过程类同,且使整个问题的搜索范围缩小了一步,所以回溯算法也属于递归算法。
迷宫
设计求解迷宫问题的算法并用实际例子测试。迷宫问题描述:一个迷宫是一些互相连通的交叉路口的集合,给定一个迷宫入口,一个迷宫出口,当从入口到出口存在通路时,输出其中的一条通路,当从入口到出口不存在通路时,输出无通路存在。每个交叉路口,除进来的路外还有三个路口,分别是向左、向前和向右。为简化设计,假设迷宫中不存在环路。图6-8所示是一个没有环路的迷宫示意图。
图6-8 迷宫问题【问题分析】 迷宫问题中包括有很多路口,每个路口最多有三个搜索分支,把算法设计为如下的搜索过程:把整个搜索分解为向左、向前和向右三个方向上子问题的搜索。当搜索到某个路口(设该路口为C)、发现该路口没有可搜索方向时,就让搜索过程回溯退到该路口的前一路口(设该路口为B),然后搜索这个路口(即路口B)的其他尚未搜索过的搜索方向;如果发现这个路口(即路口 B)也没有可搜索方向时,就让搜索过程继续回溯退到这个路口的前一路口(设该路口为 A)继续这样的搜索过程。这样的搜索过程一直进行到找到出口或搜索完了全部可连通的路口的可能搜索方向没有找到出口为止。
代码测试
/*
回溯算法求迷宫
*/
#include <stdio.h>
#include <stdlib.h>
/*============== 路的结构体 ================*/
typedef struct{
int left; //向左方向
int forward; //向前
int right; //向右
}InterSection;
/*=============== 迷宫的结构体 ==================*/
typedef struct{
int mazeSize; //路口个数
InterSection *intSec; //路口集合
int Exit; //出口
}Maze;
/*
用回溯算法搜索迷宫的所有分支,
参数currSetValue为当前所处的路口
*/
int TravMaze(Maze *m, int currSetValue){
if(currSetValue>0){ //有路径存在,可以继续探索发现一下路径
if(currSetValue==m->Exit){ //递归出口
printf("%d<==",currSetValue);//输出路径
return 1;
}else if(TravMaze(m,m->intSec[currSetValue].left)==1){ //向左
//只有探索成功,返回值为1,才执行以下语句
printf("%d<==",currSetValue);
return 1;
}else if(TravMaze(m,m->intSec[currSetValue].forward)==1){ //向前
printf("%d<==",currSetValue);
return 1;
}else if(TravMaze(m,m->intSec[currSetValue].right)==1){ //向右
printf("%d<==",currSetValue);
return 1;
}
}
return 0;
}
/*
创建迷宫
根据filename中存放的数据创建迷宫
*/
void CreatMaze(char *filename, Maze *m){
FILE *fp;
int i;
fp = fopen(filename,"r"); //以读方式打开文件
if(!fp){
printf("file open faile!");
return;
}
fscanf(fp,"%d",&m->mazeSize); //读取
m->intSec = (InterSection*)malloc(sizeof(InterSection)*(m->mazeSize+1));//建立mazeSize+1个元素数组
for(i=1;i<=m->mazeSize;i++){
fscanf(fp,"%d%d%d",&m->intSec[i].left,&m->intSec[i].forward,&m->intSec[i].right);
}
fscanf(fp,"%d%d%d",&m->Exit);//读入出口数
fclose(fp); //关闭文件
}
/*================== 测试主函数 =============================*/
void main(void){
Maze m;
int start = 1;
CreatMaze("Maze.dat",&m);
if(TravMaze(&m,start)){
printf("\n此迷宫的一条通路如上所示!");
}else{
printf("\n此迷宫无解!");
}
getch();
}