数据放在1.h文件,自己估计了一个二维坐标各个城市的坐标值用于启发式函数。
链接: https://pan.baidu.com/s/133PwUZplnTVdmPZBVIo5HQ?pwd=26wt
提取码: 26wt
M.cpp文件
#include<iostream>
#include<queue>
#include<vector>
#include<stack>
#include<string>
#include<time.h>
#include<cmath>
#include<unordered_map>
#include"1.h"//存放数据
using namespace std;
struct City
{
string nym; //城市名称
int val=0,gn=0,hn=0; //val,gn,hn 分别对应A*算法公式 f(n)=g(n)+h(n)
int father=-1;
int x,y; //估计的二维坐标中坐标
};
class Graph
{
public:
Graph();
int graph[20][20]; //邻接矩阵
City city[20];
};
Graph::Graph() //初始化表和城市节点
{
for(int i=0;i<20;i++)
{
for(int j=0;j<20;j++)
{
graph[i][j]=g[i][j];
}
city[i].nym=name[i];
city[i].x=h[i][0];
city[i].y=h[i][1];
}
}
-----------------------------深度优先搜索---------------------------------------------
void dfs(int start,int end)
{
stack<int> openlist; //open表
Graph G;
long long int time1=clock(); //记录时间
int x=start;
bool seek[20]={false}; //记录访问的城市,默认false,访问后true
openlist.push(x); //放入起始地,从起点开始遍历
stack<string> road;
while(!openlist.empty())
{
x=openlist.top();
if(x==end)break; //遍历到终点直接结束
openlist.pop();
for(int i=19;i>0;i--)
{
if(G.graph[x][i]>1&&G.graph[x][i]<1000&&!seek[i])
{
seek[i]=true;
G.city[i].father=x; //记录父节点便于后面输出
openlist.push(i); //将该城市序号放入open表
}
}
}
while(1) //用栈整理出路径
{
//cout<<" "<<G.city[x].nym; //用于调试
road.push(G.city[x].nym);
x=G.city[x].father;
if(x==start)
{
road.push(G.city[x].nym);
break;
}
}
cout<<"dfs搜索出路径为:"<<road.top();
road.pop();
while(!road.empty())
{
cout<<"->"<<road.top();
road.pop();
}
long long int time2=clock();
cout<<endl<<"耗时:"<<time2-time1<<"ms"<<endl;
}
------------------------------广度优先搜索-----------------------------------------
//类似于深度优先搜索,不过这里用的是队列,深度优先搜索用的是栈
void bfs(int start,int end)
{
queue<int> openlist;
Graph G;
long long int time1=clock();
int x=start;
stack<string> road;
bool seek[20]={false};
openlist.push(x);
seek[x]=true;
while(!openlist.empty())
{
x=openlist.front();
if(x==end)break;
for(int i=0;i<20;i++)
{
if(G.graph[x][i]>1&&G.graph[x][i]<1000&&!seek[i])
{
seek[i]=true;
G.city[i].father=x;
openlist.push(i);
}
}
openlist.pop();
}
while(1)
{
road.push(G.city[x].nym);
x=G.city[x].father;
if(x=start)
{
road.push(G.city[x].nym);
break;
}
}
cout<<"bfs搜索出路径为:"<<road.top();
road.pop();
while(!road.empty())
{
cout<<"->"<<road.top();
road.pop();
}
long long int time2=clock();
cout<<endl<<"耗时:"<<time2-time1<<"ms"<<endl;
}
----------------------------A*算法-------------------------------------------------------
//方便排序用了优先队列
void A_(int start,int end)
{
Graph G;
auto cmp=[&G](int a,int b)
{
return G.city[a].val<G.city[b].val;
};
priority_queue<int,vector<int>,decltype(cmp)> openlist(cmp);
//定义一个可以根据序号x的G.city[x].val值进行排序的open表
long long int time1=clock();
openlist.push(start);
int x;
G.city[start].gn=0;
bool seek[20]={false};
stack<string> road;
while(!openlist.empty())
{
x=openlist.top();
if(x==end)break;
for(int i=0;i<20;i++)
{
if(G.graph[x][i]>0 && G.graph[x][i]<1000 && !seek[i])
{
G.city[i].gn=G.graph[x][i]+G.city[x].gn;
G.city[i].hn=sqrt(pow((G.city[end].x-G.city[i].x),2)+pow((G.city[end].y-G.city[i].y),2));
G.city[i].val=G.city[i].gn+G.city[i].hn;
//计算节点的f(n)
openlist.push(i);
seek[i]=true;
G.city[i].father=x;
}
}
openlist.pop();
}
while(1)
{
road.push(G.city[x].nym);
x=G.city[x].father;
if(x==start)
{
road.push(G.city[x].nym);
break;
}
}
cout<<"A*搜索出路径为:"<<road.top();
road.pop();
while(!road.empty())
{
cout<<"->"<<road.top();
road.pop();
}
long long int time2=clock();
cout<<endl<<"耗时:"<<time2-time1<<"ms"<<endl;
}
unordered_map<string,int> citylist={{"Arad",0},{"Mehadia",1},{"Bucharest",2},{"Neamt",3},{"Craiova",4},{"Oradea",5},{"Doberta",6},
{"Pitesti",7},{"Eforie",8},{"Rimmicu_Vikea",9},{"Fagaras",10},{"Sibiu",11},{"Giurgiu",12},{"Timisoara",13},
{"Hirsova",14},{"Urziceni",15},{"Iasi",16},{"Vaslui",17},{"Lugoj",18},{"Zerind",19}};
//使用哈希表解决输入城市名字转化为序号的问题
int main()
{
string start,end;
int mode;
cout<<"输入起点城市的名字:"<<endl;
cin>>start;
cout<<"输入终点城市的名字:"<<endl;
cin>>end;
cout<<"1.深度优先搜索"<<endl<<"2.广度优先搜索"<<endl<<"3.A*算法搜索"<<endl<<"选择算法(序号):";
cin>>mode;
switch (mode)
{
case 1:
dfs(citylist[start],citylist[end]);
break;
case 2:
bfs(citylist[start],citylist[end]);
break;
case 3:
A_(citylist[start],citylist[end]);
break;
default:
break;
}
}