为带权图生成邻接矩阵

11

我正在尝试实现弗洛伊德-沃尔夏尔算法。为此,我需要设置一个带权有向图的邻接矩阵。我该如何做?我知道数值,并附上了带权图的图片。我已经尝试寻找一些在线示例,但貌似找不到任何东西。我理解弗洛伊德-沃尔夏尔算法,但我需要帮助设置它,以便我能够实现它。这是我之前构建过的一个示例,但我没有使用特定的值。

代码:

public static void buildAdjMatrix()
{

    for (int i = 0; i < 100; i++)
    {
        for (int j = 0; j < 100; j++)
        {
            if (directionAllowed(i, j) == true)
            {
                adjMatrix[i, j] = 1;
            }
            else
            {
                adjMatrix[i, j] = 50;
            }
        }
    }

}

这里是手头的具体图表:

图片描述

这是我需要创建的矩阵的图片。抱歉图片质量很差...

图片描述


发布您正在使用的图形结构,例如NodeArc类,将会非常有用。 - RMalke
我不太确定你的意思。抱歉 :( - JLott
@JLott,你说的“specific values”是什么意思? - educampver
添加了矩阵的图片。 - JLott
1个回答

51

看起来您对于图形不太熟悉,可以去维基百科了解一下,并浏览一些图片,这样更容易理解。

概念简介

您的图片可以被视为一个图形(Graph)。通常,图形使用两种基本元素实现,即 节点(Nodes)链接(Links)(有时称为弧(Arcs))。

节点(Node)代表图片中的字母,例如A、B、C等。一个链接(Arc)连接(Link)是连接两个节点的线条,如果您查看H到L之间的连接,它们之间就有一条链接,在加权图中,不同的链接具有不同的权重。

解决问题 - 第1部分

我们需要在代码中将您的图片表示为一个图形,因此让我们开始创建基本元素节点(Node)链接(Arc)

节点(Node)

一个节点具有名称(Name),以便我们可以识别节点。节点可以与其他节点连接,我们可以使用一组节点,但是由于您的图是加权图,因此每个连接都必须由链接节点及其权重表示。因此,我们使用一组链接(Arcs)

public class Node
{
    public string Name;
    public List<Arc> Arcs = new List<Arc>();

    public Node(string name)
    {
        Name = name;
    }

    /// <summary>
    /// Create a new arc, connecting this Node to the Nod passed in the parameter
    /// Also, it creates the inversed node in the passed node
    /// </summary>
    public Node AddArc(Node child, int w)
    {
        Arcs.Add(new Arc
        {
            Parent = this,
            Child = child,
            Weigth = w
        });

        if (!child.Arcs.Exists(a => a.Parent == child && a.Child == this))
        {
            child.AddArc(this, w);
        }

        return this;
    }
}

Arc

这是一个非常简单的类,它包含了连接的节点和连接的权重:

public class Arc
{
    public int Weigth;
    public Node Parent;
    public Node Child;
}

图形

图形是一种包装类,用于组织目的。我还声明了一个图形的根部,虽然我们没有使用它,但在几种情况下它很有用:

public class Graph
{
    public Node Root;
    public List<Node> AllNodes = new List<Node>();

    public Node CreateRoot(string name)
    {
        Root = CreateNode(name);
        return Root;
    }

    public Node CreateNode(string name)
    {
        var n = new Node(name);
        AllNodes.Add(n);
        return n;
    }

    public int?[,] CreateAdjMatrix()
    {
        // Matrix will be created here...
    }
}

解决您的问题 - 第2部分

现在我们已经拥有了包含图形的所有数据结构,让我们填充一些数据。以下是一些初始化类似于您方块图片的图形的代码。虽然它很无聊和单调,但在真实情况下,图将动态创建:

static void Main(string[] args)
{
    var graph = new Graph();

    var a = graph.CreateRoot("A");
    var b = graph.CreateNode("B");
    var c = graph.CreateNode("C");
    var d = graph.CreateNode("D");
    var e = graph.CreateNode("E");
    var f = graph.CreateNode("F");
    var g = graph.CreateNode("G");
    var h = graph.CreateNode("H");
    var i = graph.CreateNode("I");
    var j = graph.CreateNode("J");
    var k = graph.CreateNode("K");
    var l = graph.CreateNode("L");
    var m = graph.CreateNode("M");
    var n = graph.CreateNode("N");
    var o = graph.CreateNode("O");
    var p = graph.CreateNode("P");

    a.AddArc(b, 1)
     .AddArc(c, 1);

    b.AddArc(e, 1)
     .AddArc(d, 3);

    c.AddArc(f, 1)
     .AddArc(d, 3);

    c.AddArc(f, 1)
     .AddArc(d, 3);

    d.AddArc(h, 8);

    e.AddArc(g, 1)
     .AddArc(h, 3);

    f.AddArc(h, 3)
     .AddArc(i, 1);

    g.AddArc(j, 3)
     .AddArc(l, 1);

    h.AddArc(j, 8)
     .AddArc(k, 8)
     .AddArc(m, 3);

    i.AddArc(k, 3)
     .AddArc(n, 1);

    j.AddArc(o, 3);

    k.AddArc(p, 3);

    l.AddArc(o, 1);

    m.AddArc(o, 1)
     .AddArc(p, 1);

    n.AddArc(p, 1);

    // o - Already added

    // p - Already added

    int?[,] adj = graph.CreateAdjMatrix(); // We're going to implement that down below

    PrintMatrix(ref adj, graph.AllNodes.Count); // We're going to implement that down below
}

解决你的问题 - 第 3 部分

现在,我们有了一个完整初始化的图,让我们创建矩阵。下一个方法创建一个二维矩阵,大小为 n X n,其中 n 是从图形类获取的节点数。对于每个节点,我们搜索它们是否具有链接,如果它们具有链接,则在适当的位置填充矩阵。请注意,在你的邻接矩阵示例中,只有 1,但在这里,我把链接的权重放进去了。我这样做是为了没有意义的带权图!

public int?[,] CreateAdjMatrix()
{
    int?[,] adj = new int?[AllNodes.Count, AllNodes.Count];

    for (int i = 0; i < AllNodes.Count; i++)
    {
        Node n1 = AllNodes[i];

        for (int j = 0; j < AllNodes.Count; j++)
        {
            Node n2 = AllNodes[j];

            var arc = n1.Arcs.FirstOrDefault(a => a.Child == n2);

            if (arc != null)
            {
                adj[i, j] = arc.Weigth;
            }
        }
    }
    return adj;
}

完成了

好的,完成了,您已经拥有了加权邻接矩阵,并且有一些打印它的方法:

private static void PrintMatrix(ref int?[,] matrix, int Count)
{
    Console.Write("       ");
    for (int i = 0; i < Count; i++)
    {
        Console.Write("{0}  ", (char)('A' + i));
    }

    Console.WriteLine();

    for (int i = 0; i < Count; i++)
    {
        Console.Write("{0} | [ ", (char)('A' + i));

        for (int j = 0; j < Count; j++)
        {
            if (i == j)
            {
                Console.Write(" &,");
            }
            else if (matrix[i, j] == null)
            {
                Console.Write(" .,");
            }
            else
            {
                Console.Write(" {0},", matrix[i, j]);
            }

        }
        Console.Write(" ]\r\n");
    }
    Console.Write("\r\n");
}

以下代码会输出什么结果:

       A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P
A | [  &, 1, 1, ., ., ., ., ., ., ., ., ., ., ., ., ., ]
B | [  1, &, ., 3, 1, ., ., ., ., ., ., ., ., ., ., ., ]
C | [  1, ., &, 3, ., 1, ., ., ., ., ., ., ., ., ., ., ]
D | [  ., 3, 3, &, ., ., ., 8, ., ., ., ., ., ., ., ., ]
E | [  ., 1, ., ., &, ., 1, 3, ., ., ., ., ., ., ., ., ]
F | [  ., ., 1, ., ., &, ., 3, 1, ., ., ., ., ., ., ., ]
G | [  ., ., ., ., 1, ., &, ., ., 3, ., 1, ., ., ., ., ]
H | [  ., ., ., 8, 3, 3, ., &, ., 8, 8, ., 3, ., ., ., ]
I | [  ., ., ., ., ., 1, ., ., &, ., 3, ., ., 1, ., ., ]
J | [  ., ., ., ., ., ., 3, 8, ., &, ., ., ., ., 3, ., ]
K | [  ., ., ., ., ., ., ., 8, 3, ., &, ., ., ., ., 3, ]
L | [  ., ., ., ., ., ., 1, ., ., ., ., &, ., ., 1, ., ]
M | [  ., ., ., ., ., ., ., 3, ., ., ., ., &, ., 1, 1, ]
N | [  ., ., ., ., ., ., ., ., 1, ., ., ., ., &, ., 1, ]
O | [  ., ., ., ., ., ., ., ., ., 3, ., 1, 1, ., &, ., ]
P | [  ., ., ., ., ., ., ., ., ., ., 3, ., 1, 1, ., &, ]

1
哇!这个解释太棒了!非常感谢您的帮助。这真的帮助我理解了该怎么做,我相信其他人也会觉得很有用。 - JLott
我确实遇到了一个问题。在你的CreateAdjMatrix函数中,它说在计数器“i”的for循环中有无法访问的代码。 - JLott
太棒了。我刚刚把我的括号顺序搞错了...当然啦。再次感谢! - JLott
哇!!RMalke,你的数据结构太强了!!+1 给你详细的解释。 - user1312242
1
@Celsiuss 是的。它实现在第三部分,方法名为 CreateAdjMatrix - RMalke
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接