万金流
以码会友。 吾Q:578751655。 水平有限,轻喷,谢!
随笔 - 189,  文章 - 0,  评论 - 7,  阅读 - 14万

如题。

例图如下:

 

借用之前“简单图” 的代码生成图,并进行修改和补充。

图顶点代码:

复制代码
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:\Hc\1\ConsoleApp1\ConsoleApp1\1.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}\t");
                }
                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
复制代码

 

posted on   万金流  阅读(296)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现

点击右上角即可分享
微信分享提示