设计目的
熟练掌握迪杰斯特拉算法和费洛伊德算法,能够利用它们解决最短路径问题。
掌握图的深度,广度遍历算法。
掌握快速排序算法。
效果图
需求分析
1, 将word文件转化为csv文件,读取全国城市距离表和全国城市邻接表,动态加载到内存中。
2, 用DFS算法设置深搜的深度验证其他省会到武汉中间不超过两个省会城市。
3, 用迪杰斯特拉算法和佛洛依德算法求解任意两个城市间的最短路径并输出。
4, 用DFS算法设置深搜深度限制中间经过城市数量,并用数组动态维护探查路径,将所有可行路径存储起来,用快排进行排序,之后输出到文件。
5, 用迪杰斯特拉算法和佛洛依德算法求两个城市间最短路径,并限制不经过某城市。
6,用YEN算法求解任意两个城市间前k短路径。
概要设计
1, 考虑csv存储格式以“,”划分,文件读取操作将“,”转化为空格,用stringstream流分割读取,自动进行格式转换。
While(getline(in,s)){
1,“,”->“ ”
2,stringstream分割读取
}
2,void DFS(){
if(当前深搜得到武汉) 输出当前路径并return;
if(深搜深度超过阈值)return;
dfs主体常规递归;
}
3,裸迪杰斯特拉算法和佛洛依德算法直接求解即可
4,void DFSpro(){
if(当前深搜到目的地){输出数组中路径信息并return}
If(深搜深度超过阈值){return}
Dfs主题递归{注意:每次return后需要对节点重新标记,因为需要多次访问}
}
5,迪杰斯特拉算法:if(要加入s集合的节点是要绕过的节点)continue;
佛洛依德算法:if(每次要插入的节点是要绕过的节点)continue;
6,void Astar(){
1,调用迪杰斯特拉算法求出第一条最短路径;
2,while(当前求第k短路径)
While(遍历第k-1短路径当中的所有偏离点)
求出当前偏离点对应的不能走的顶点和边;
基于不能走的顶点和边调用迪杰斯特拉算法求出候选路径;
3,对第k-1短路径中所有偏离点对应的候选路径排序,取出最短的路径作为第k短路径;
详细设计
1,for (int i = 0; i < s.size(); i++){//考虑文件格式,将特殊符号均置为空格符
if (s[i] == ',') s[i] = ' ';
}
stringstream ss;
ss << s;
while (ss>>temp[n]){
if (k == 0) vlist[m].data = temp[n], n--;//去除第一行杂项
else earry[m][n] =earry[n][m]=atoi(temp[n].c_str());//读取信息存入矩阵
n++; k++;
}
2,void DFS(){
if (vlist[v].data == "武汉"&&flag)//首次深搜得到武汉 输出路径并跳出
if (time > 2){//深搜深度不超过3
path[time] = " ";//超过 且不是武汉 则回退
return;
}
3,迪杰斯特拉算法和佛洛依德算法直接调用;
4,void DFSpro(){
if (vlist[v].data == vlist[q].data )//如果目前深搜得到目的地就输出并return
if (time > 10){//深搜深度不超过9
path[time] = " ";//超过 且不是武汉 则回退
return;
}
5,dij:int u = v;
for (j = 0; j < numv; j++){
if (j == p) continue;// 跳过需要绕过的城市顶点
if (s[j] == false && dist[j] < min){
u = j;
min = dist[j];
}
}
floyd:for (int k = 0; k < numv; k++)
if (k == q) continue;//如果插入节点是要绕过的节点 那么不插入 直接跳过
6,void graph::Astar(graph& G, int v, int p, int k){
G.singledij(G, v, p, unavilablenode, unavilableedge);// 调用dij求出第一短;
while (kk < k){
for (int i = 0; i < num-1; i++)//遍历每一个偏离点
for (int j = 0; j < i; j++)
unavilablenode[j] = getloc(finalpath[kk - 1].arr[j]); //不能走的顶点
unavilableedge[edgenum].begin = pianli;// //不能走的边
unavilableedge[edgenum].end = getloc(finalpath[kkk - 1].arr[j + 1]);
G.singledij(G, pianli, p, unavilablenode, unavilableedge);//调dij求候选路径
sortpath(houxuanpath, houxuanpath + G.Atime, cmp);
finalpath[kk] = houxuanpath[0];// 排序取第一条最短作为第k短
}
优化反思
1, 从全国其他城市调用DFS判断是否深搜的得到武汉,调用多次DFS,因此可以从武汉出发,对全国其他城市做标记,遍历所有城市,依旧设置递归深度,可以调用依次DFS就验证全国城市到武汉不超过两个省会;
2, 求第k短路径是,需要多次调用dij求候选路径,因此可以在dij算法中做改进,对每次加顶点后形成的dist矩阵做处理,从起点开始,每一次试探所有课行顶点,并将所有可行路径存储起来,排序后选出k短路径;