C# 遍历用邻接矩阵表示的图

C# 遍历用邻接矩阵表示的图,c#,matrix,traversal,depth-first-search,breadth-first-search,C#,Matrix,Traversal,Depth First Search,Breadth First Search,我想使用深度优先和广度优先的方法来遍历图形。我以前在一个简单的节点列表上做过这项工作,但我从未尝试过使用邻接矩阵,而且我真的不知道从哪里开始 这是我的矩阵: 999999999 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 999999999 0 3 1 0 0 0 0 0 0 0 0 0 0 0 1 0 999999999 3 0 1 0 0 0 0 0 0 0 0 0 0 0 3 3 999999999 0 0 0 8 0 0 0 0 0 0 0 0 0 1 0 0

我想使用深度优先和广度优先的方法来遍历图形。我以前在一个简单的节点列表上做过这项工作,但我从未尝试过使用邻接矩阵,而且我真的不知道从哪里开始

这是我的矩阵:

999999999 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 
1 999999999 0 3 1 0 0 0 0 0 0 0 0 0 0 0 
1 0 999999999 3 0 1 0 0 0 0 0 0 0 0 0 0 
0 3 3 999999999 0 0 0 8 0 0 0 0 0 0 0 0 
0 1 0 0 999999999 0 1 3 0 0 0 0 0 0 0 0 
0 0 1 0 0 999999999 0 3 1 0 0 0 0 0 0 0 
0 0 0 0 1 0 999999999 0 0 3 0 1 0 0 0 0 
0 0 0 8 3 3 0 999999999 0 8 8 0 3 0 0 0 
0 0 0 0 0 1 0 0 999999999 0 3 0 0 1 0 0 
0 0 0 0 0 0 3 8 0 999999999 0 0 0 0 3 0 
0 0 0 0 0 0 0 8 3 0 999999999 0 0 0 0 3 
0 0 0 0 0 0 1 0 0 0 0 999999999 0 0 1 0 
0 0 0 0 0 0 0 3 0 0 0 0 999999999 0 1 1 
0 0 0 0 0 0 0 0 1 0 0 0 0 999999999 0 1 
0 0 0 0 0 0 0 0 0 3 0 1 1 0 999999999 0 
0 0 0 0 0 0 0 0 0 0 3 0 1 1 0 999999999
下面是我如何创建这个矩阵(C#):

private static int[,]CreateMatrix()
{
int A=0;
int B=1;
int C=2;
int D=3;
int E=4;
int F=5;
int G=6;
int H=7;
int I=8;
int J=9;
int K=10;
int L=11;
int M=12;
int N=13;
INTO=14;
int P=15;
int[,]矩阵=新的int[16,16];
矩阵[A,B]=1;
矩阵[A,C]=1;
矩阵[B,D]=3;
矩阵[B,E]=1;
矩阵[C,D]=3;
矩阵[C,F]=1;
矩阵[D,H]=8;
矩阵[E,G]=1;
矩阵[E,H]=3;
矩阵[F,H]=3;
矩阵[F,I]=1;
矩阵[G,J]=3;
矩阵[G,L]=1;
矩阵[H,J]=8;
矩阵[H,K]=8;
矩阵[H,M]=3;
矩阵[I,K]=3;
矩阵[I,N]=1;
矩阵[J,O]=3;
矩阵[K,P]=3;
矩阵[L,O]=1;
矩阵[M,O]=1;
矩阵[M,P]=1;
矩阵[N,P]=1;
矩阵[B,A]=1;
矩阵[C,A]=1;
矩阵[D,B]=3;
矩阵[E,B]=1;
矩阵[D,C]=3;
矩阵[F,C]=1;
矩阵[H,D]=8;
矩阵[G,E]=1;
矩阵[H,E]=3;
矩阵[H,F]=3;
矩阵[I,F]=1;
矩阵[J,G]=3;
矩阵[L,G]=1;
矩阵[J,H]=8;
矩阵[K,H]=8;
矩阵[M,H]=3;
矩阵[K,I]=3;
矩阵[N,I]=1;
矩阵[O,J]=3;
矩阵[P,K]=3;
矩阵[O,L]=1;
矩阵[O,M]=1;
矩阵[P,M]=1;
矩阵[P,N]=1;
对于(int i=0;i<16;i++)
{
对于(int j=0;j<16;j++)
{
if(矩阵[i,j]==0)
矩阵[i,j]=0;
如果(i==j)
矩阵[i,j]=9999999;
}
}
收益矩阵;
}
任何帮助都将不胜感激

此矩阵表示的图形:


计算机科学中的每一个问题,除了一个,都可以通过增加更多的抽象来解决

void BreadthFirstTraversal(Graph graph, Vertex start)
{
    var queue = new VertexQueue();
    var markSet = new VertexMarkSet();
    queue.Enqueue(start);
    markSet.Add(start);
    while(queue.NotEmpty())
    {
        var vertex = queue.Dequeue();
        foreach(Vertex neighbour in graph.ListNeighbours(vertex))
        {
            if (!markSet.Contains(neighbour))
            {
                markSet.Add(neighbour);
                queue.Enqueue(neighbour);
            }
        }
     }
}
首先以最抽象的方式编写广度优先遍历:

void BreadthFirstTraversal(Graph graph, Vertex start)
{
    /* A miracle happens */
}
我们有一种方法可以满足我们的需求。除了它还没有被写出来。因此,用稍微少一点的抽象来写它:

继续,删除越来越多的抽象

void BreadthFirstTraversal(Graph graph, Vertex start)
{
    var queue = new VertexQueue();
    var markSet = new VertexMarkSet();
    queue.Enqueue(start);
    markSet.Add(start);
    while(queue.NotEmpty())
    {
        var vertex = queue.Dequeue();
        foreach(Vertex neighbour in graph.ListNeighbours(vertex))
        {
            if (!markSet.Contains(neighbour))
            {
                markSet.Add(neighbour);
                queue.Enqueue(neighbour);
            }
        }
     }
}
好的,现在你已经有了一个算法,它适用于任何图形,不管它的内部表示是什么。因此,您所要做的就是编写
列表邻居(顶点)
,就完成了。(假设您已经知道如何编写队列和集合,或者愿意使用基类库附带的类型。)您将如何做到这一点

你知道我是怎么使用抽象的吗?我真的不在乎它是一个邻接矩阵还是一个邻接列表,我所关心的只是这个图提供给我一个顶点的邻域

那么,在给定邻接矩阵的情况下,如何编写
列表邻居(顶点)

两种可能的调查解决方案:

  • 使
    Graph.listNeights(Vertex)
    方法返回一个
    列表
    。编制清单并分发出去

  • 使其返回
    IEnumerable
    ,并使用
    yield return
    生成相邻顶点的序列


更新:好的,那么我们如何从邻接矩阵中生成一个邻接序列呢

假设每个顶点都有编号,所以
顶点
实际上是
int
;这是处理邻接矩阵的传统方法。我们想要取一个顶点,一个int,然后返回一系列与其相邻的顶点

如果顶点
j
是顶点
i
的近邻,则具有
array[i,j]
非零属性的数组

同样,从抽象开始,以您的方式实现:

public List<int> ListNeighbours(int vertex)
{
    /* a miracle happens */
}

yield-return
迭代器往往更简单,但初学者通常很难使用控制流试着用两种方式写,看看它是怎么写的。

哈哈,是的,这是我在这个例子中真正的问题好奇的撅嘴,什么是一个不能通过增加更多抽象来解决的问题???@JLott:“我的程序包含了太多的抽象”。好吧。。我不会说谎。。。我甚至不知道从哪里开始建立这个方法。。。我已经试着去查了,但谷歌在这种情况下并不是最好的。@JLott:我已经添加了一些提示。当我刚开始实习时,我就是这样写我所有的程序的,就像你在这里看到的。首先编写一个只具有正确签名的方法,然后填写一个高级描述,然后将其分解为多个步骤,并继续分解,直到我能够真正编写每个步骤的代码;为什么它不是布尔矩阵?它是一个加权图。我将发布它所代表的图形的图片。明白了。有些人使用带有计数的邻接图来表示两个节点之间有多少条边,这在您的场景中是没有意义的。为了一个可能
public List<int> ListNeighbours(int vertex)
{
    /* a miracle happens */
}
public List<int> ListNeighbours(int vertex)
{
    /* create a new list */
    /* for each vertex j in the graph */
        /* if j is a neighbour of i then add it to the list */
    /* return the list */
}
public IEnumerable<int> ListNeighbours(int vertex)
{
    /* for each vertex j in the graph */
        /* if j is a neighbour of i then yield return j */
}