寻路算法在生活中应用十分常见。本文实现的是关于图的最短路径查找算法。
该算法比较常见于游戏和室内地图导航。
例子:几个节点之间,相连接的线段有固定长度,该长度决就是通过代价。查找到花费最少的路径。该图结构为
可以看到 A>B>D与A>C>D 的代价都相同,边相加都等于10. 而A>C>B的路线代价扽与9,是最短路径。
复杂度:最坏情况应该就是O((n-1)2) 了吧
//csharp版代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
namespace ConsoleApp1test
{
class Program
{ //创建图数据
static Hashtable myGraph = new Hashtable();
static void Main(string[] args)
{
//A节点及其信息与关系
myGraph["A"] = new Hashtable();
(myGraph["A"] as Hashtable)["B"] = 5;
(myGraph["A"] as Hashtable)["C"] = 2;
(myGraph["A"] as Hashtable)["F"] = 2;
//B节点
myGraph["B"] = new Hashtable();
(myGraph["B"] as Hashtable)["D"] = 5;
(myGraph["B"] as Hashtable)["F"] = 5;
//C
myGraph["C"] = new Hashtable();
(myGraph["C"] as Hashtable)["B"] = 2;
(myGraph["C"] as Hashtable)["D"] = 8;
//D
myGraph["D"] = new Hashtable();
//f
myGraph["F"] = new Hashtable();
//递归监测
GetPath(myGraph["A"] as Hashtable, "A", "D");
Console.ReadKey();
}
//创建用于存储代价的变量
static int cost = 0;
//创建用于记录路径的数据表
static Hashtable rote = new Hashtable();
static List<string> rotearray = new List<string>();
public static void GetPath(Hashtable targetNode, string startPoint, string endPoint)
{
//记录当前节点
rotearray.Add(startPoint);
Console.WriteLine("当前节点:"+ startPoint);
string st = "";
foreach (string name in rotearray)
{
st += name + ">";
}
Console.WriteLine("当前结构:"+st);
//当前节点是否是根节点
if (startPoint == endPoint)
{
//已经到达终点 //输出当前分支的每个节点
string s = "";
foreach (string name in rotearray)
{
s += name + ">";
}
Console.WriteLine("到达终点,路径:"+s);
Console.WriteLine("=================");
} else {
//未到达指定节点 遍历每个节点下相关联的子节点
foreach (string connected_node_name in targetNode.Keys)//在第一次输入时,不应该遍历所有的值
{
GetPath(myGraph[connected_node_name] as Hashtable, connected_node_name, endPoint);
}
}
//删除当前节点回 到上层
if (rotearray.Count > 0)
rotearray.RemoveAt(rotearray.Count - 1);
}
}
}
结果:
当前节点:A
当前结构:A>
当前节点:C
当前结构:A>C>
当前节点:D
当前结构:A>C>D>
到达终点,路径:A>C>D>
=================
当前节点:B
当前结构:A>C>B>
当前节点:F
当前结构:A>C>B>F>
当前节点:D
当前结构:A>C>B>D>
到达终点,路径:A>C>B>D>
=================
当前节点:F
当前结构:A>F>
当前节点:B
当前结构:A>B>
当前节点:F
当前结构:A>B>F>
当前节点:D
当前结构:A>B>D>
到达终点,路径:A>B>D>
=================
此段代码,用于求出加权图最短路径,加入了防循环,可以在有向图、无向图中使用
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
namespace ConsoleApp1test
{
class Program
{
//创建图数据
static Hashtable myGraph = new Hashtable();
static void Main(string[] args)
{
//A节点及其信息与关系
myGraph["A"] = new Hashtable();
(myGraph["A"] as Hashtable)["B"] = 5;
(myGraph["A"] as Hashtable)["C"] = 2;
(myGraph["A"] as Hashtable)["F"] = 2;
//B节点
myGraph["B"] = new Hashtable();
(myGraph["B"] as Hashtable)["D"] = 5;
(myGraph["B"] as Hashtable)["F"] = 5;
//C
myGraph["C"] = new Hashtable();
(myGraph["C"] as Hashtable)["B"] = 2;
(myGraph["C"] as Hashtable)["D"] = 8;
//D
myGraph["D"] = new Hashtable();
//f
myGraph["F"] = new Hashtable();
(myGraph["F"] as Hashtable)["B"] = 2;
//递归监测
GetPath(myGraph["A"] as Hashtable, "A", "D");
Console.WriteLine("最短路径:" + shortestPath + " 代价:" + shortestCost + "米");
Console.ReadKey();
}
//创建用于存储代价\记录路径的数据表
static List<string> pathList = new List<string>();
static List<int> pathCostList = new List<int>();
static int shortestCost = 100000;
static string shortestPath = "";
public static void GetPath(Hashtable targetNode, string startPoint, string endPoint)
{
//记录当前节点
pathList.Add(startPoint);
Console.WriteLine("当前节点:"+ startPoint);
string allPath = "";
for(int i=0; i < pathList.Count; i++)
{
allPath += pathList[i];
allPath += (i == (pathList.Count - 1)) ? "" : ">";
}
Console.WriteLine("当前结构:" + allPath);
//当前节点是否是根节点
if (startPoint == endPoint)
{
//已经到达终点 //输出当前分支的每个节点
Console.WriteLine("到达终点,路径:"+ allPath);
//计算所有的权值
int pathCost_total = 0;
foreach (int pathCost in pathCostList)
{
pathCost_total += pathCost;
}
Console.WriteLine("代价:" + pathCost_total.ToString() + "米");
//更新最短路径信息
if (pathCost_total < shortestCost) {
shortestCost = pathCost_total;
shortestPath = allPath;
}
Console.WriteLine("==========害羞而淫荡的分割线==========");
} else {
//未到达指定节点 遍历每个节点下相关联的子节点
foreach (string connected_node_name in targetNode.Keys)
{
//如果,路径中已存在节点,就不走了。 避免循环。
if (!pathList.Contains(connected_node_name)) {
//记录路径权值
pathCostList.Add((int)targetNode[connected_node_name]);
GetPath(myGraph[connected_node_name] as Hashtable, connected_node_name, endPoint);
//记录路径权值
if (pathCostList.Count > 0)
pathCostList.RemoveAt(pathCostList.Count - 1);
}
}
}
//删除当前节点回 到上层
if (pathList.Count > 0)
pathList.RemoveAt(pathList.Count - 1);
}
}
}
结果:
当前节点:A
当前结构:A
当前节点:C
当前结构:A>C
当前节点:D
当前结构:A>C>D
到达终点,路径:A>C>D
代价:10米
==========害羞而淫荡的分割线==========
当前节点:B
当前结构:A>C>B
当前节点:F
当前结构:A>C>B>F
当前节点:D
当前结构:A>C>B>D
到达终点,路径:A>C>B>D
代价:9米
==========害羞而淫荡的分割线==========
当前节点:F
当前结构:A>F
当前节点:B
当前结构:A>F>B
当前节点:D
当前结构:A>F>B>D
到达终点,路径:A>F>B>D
代价:9米
==========害羞而淫荡的分割线==========
当前节点:B
当前结构:A>B
当前节点:F
当前结构:A>B>F
当前节点:D
当前结构:A>B>D
到达终点,路径:A>B>D
代价:10米
==========害羞而淫荡的分割线==========
最短路径:A>C>B>D 代价:9米
有权图,理论上来说把权化为等量节点,也可以使用最短节点算法求最短路径。