zoukankan      html  css  js  c++  java
  • 单源最短路径-邻接表无向网络

    如题。

    例图如下:

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

    图顶点代码:

    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
  • 相关阅读:
    AJAX
    前端上传文件 后端PHP获取文件
    PHP基础语法
    JS错误记录
    JS学习笔记
    python利用xlrd读取excel文件始终报错原因
    安装xlwt和xlrd
    编程菜鸟的日记-Linux无处不在
    编程菜鸟的日记-《软件测试》Ron Patton著-读书笔记
    编程菜鸟的日记-初学尝试编程-C++ Primer Plus 第6章编程练习9
  • 原文地址:https://www.cnblogs.com/wanjinliu/p/14175857.html
Copyright © 2011-2022 走看看