如题。
例图如下:
借用之前“简单图” 的代码生成图,并进行修改和补充。
图顶点代码:
class Node { public string v; public LinkedList<Edge> next; public Node(string x) { v = x; } }
图的边代码:
class Edge { public int index; public int edge_weight; public Edge(int x,int y) { index = x; edge_weight = y; } }
新建一个节点类Node1,用于保存结果:
class Node1 { //到顶点的最短路径。减100是防止运算的时候越界 //因为图中最大的边权值也不到100 public int path_value=int.MaxValue-100; //通往最短路径的上一个节点 public int pre_node = -1; }
图类代码:
class MyTable { Node[] nodes; //构造方法2,获得边长为n的任意无向图 public MyTable(int n) { LinkedList<Edge> t; int j,k; StreamReader sr = new StreamReader(@"C:Hc1ConsoleApp1ConsoleApp11.txt", Encoding.Default); if (n == -1) { Console.WriteLine("输入图中节点的个数:"); n = int.Parse(Console.ReadLine()); } nodes = new Node[n]; Console.WriteLine("输入每个节点的名称(每个名称回车结束)"); for (int i = 0; i < n; i++) { nodes[i] = new Node(sr.ReadLine()); } for (int i = 0; i < n; i++) { Console.WriteLine($"输入节点{nodes[i].v}的边(序号表示,每个序号回车,-1结束)"); j = int.Parse(sr.ReadLine()); Console.WriteLine($"输入该边的路径权值"); k = int.Parse(sr.ReadLine()); t = new(); do { t.AddLast(new Edge(j,k)); j = int.Parse(sr.ReadLine()); k = int.Parse(sr.ReadLine()); } while (j != -1); nodes[i].next = t; } } //按构造输入的方式输出图,测试用。 public void testShow() { foreach (var item in nodes) { Console.Write($"节点{item.v},边:"); foreach (var item1 in item.next) { Console.Write($"{nodes[item1.index].v},路径长度:{item1.edge_weight} "); } Console.WriteLine(); } } //获取指定节点的单源最短路径 //思路:遍历(用顶点数组遍历)所有节点,填入最短路径信息,直到再无变化为止。 public Node1[] get_Shortest_Path(int index) { //初始化 Node1[] b = new Node1[nodes.Length]; bool has_changed; int t; for (int i = 0; i < b.Length; i++) { b[i] = new Node1(); } b[index].path_value = 0; b[index].pre_node = index; //操作开始 do { //假设这一次遍历没有变化 has_changed = false; //遍历所有顶点 for (int i = 0; i < nodes.Length; i++) { //对遍历到的顶点,考察它所有的连接点和边 foreach (var item in nodes[i].next) { //计算该边到源点的最短路径+这条边的路径,记为t t = b[item.index].path_value + item.edge_weight; //如果t小于原来记录的最短路径 if (t<b[i].path_value) { //则刷新该顶点信息 b[i].pre_node = item.index; b[i].path_value = t; has_changed = true; } } } } while (has_changed); //操作结束 //返回 return b; } //输出最短路径数组 public void print_ShortPath(Node1[] x) { for (int i = 0; i < x.Length; i++) { Console.WriteLine($"节点:{nodes[i].v},前驱节点:{nodes[x[i].pre_node].v},路径损耗:{x[i].path_value}"); } } }
为了节约调试时间,新建了一个文件“1.txt”,里面放了初始化图的输入。
内容如下:
a b c d e f 2 14 4 9 5 7 -1 -1 2 9 3 6 -1 -1 0 14 4 2 1 9 -1 -1 5 15 4 11 1 6 -1 -1 2 2 0 9 5 10 3 11 -1 -1 0 7 4 10 3 15 -1 -1
主方法调用:
static void Main(string[] args) { int n = 6; MyTable a = new(n); a.testShow(); Console.WriteLine("请输入最短路径起点编号(整数):"); n = int.Parse(Console.ReadLine()); a.print_ShortPath(a.get_Shortest_Path(n)); }
运行结果:
节点a,边:c,路径长度:14 e,路径长度:9 f,路径长度:7 节点b,边:c,路径长度:9 d,路径长度:6 节点c,边:a,路径长度:14 e,路径长度:2 b,路径长度:9 节点d,边:f,路径长度:15 e,路径长度:11 b,路径长度:6 节点e,边:c,路径长度:2 a,路径长度:9 f,路径长度:10 d,路径长度:11 节点f,边:a,路径长度:7 e,路径长度:10 d,路径长度:15 请输入最短路径起点编号(整数): 1 节点:a,前驱节点:e,路径损耗:20 节点:b,前驱节点:b,路径损耗:0 节点:c,前驱节点:b,路径损耗:9 节点:d,前驱节点:b,路径损耗:6 节点:e,前驱节点:c,路径损耗:11 节点:f,前驱节点:e,路径损耗:21