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 */
}