c#实现图操作.docx
- 文档编号:26247009
- 上传时间:2023-06-17
- 格式:DOCX
- 页数:15
- 大小:61.12KB
c#实现图操作.docx
《c#实现图操作.docx》由会员分享,可在线阅读,更多相关《c#实现图操作.docx(15页珍藏版)》请在冰豆网上搜索。
c#实现图操作
C#实现图(Graph)
简介
图表示点之间的关系,在C#中通过节点对象的集合来表示点(Vertex),用邻接矩阵(adjacencymatrix)来表示点之间的关系。
下面来看C#实现。
PS:
本片文章是我复习的笔记,代码注释很全。
勿吐槽。
表示点的对象
下面实现代码:
classVertex
{
publicstringData;
publicboolIsVisited;
publicVertex(stringVertexdata)
{
Data=Vertexdata;
}
}
每个节点包含两个字段,分别为节点数据以及表示是否被访问过的一个布尔类型。
表示图的对象
图中除了需要点的集合和邻接矩阵之外,还需要一些基本的向图中添加或删除元素的方法,以及一个构造方法来对图进行初始化。
publicclassGraph
{
//图中所能包含的点上限
privateconstintNumber=10;
//顶点数组
privateVertex[]vertiexes;
//邻接矩阵
publicint[,]adjmatrix;
//统计当前图中有几个点
intnumVerts=0;
//初始化图
publicGraph()
{
//初始化邻接矩阵和顶点数组
adjmatrix=newInt32[Number,Number];
vertiexes=newVertex[Number];
//将代表邻接矩阵的表全初始化为0
for(inti=0;i { for(intj=0;j { adjmatrix[i,j]=0; } } } //向图中添加节点 publicvoidAddVertex(Stringv) { vertiexes[numVerts]=newVertex(v); numVerts++; } //向图中添加有向边 publicvoidAddEdge(intvertex1,intvertex2) { adjmatrix[vertex1,vertex2]=1; //adjmatrix[vertex2,vertex1]=1; } //显示点 publicvoidDisplayVert(intvertexPosition) { Console.WriteLine(vertiexes[vertexPosition]+""); } } 拓扑排序(TopSort) 拓扑排序是对一个有向的,并且不是环路的图中所有的顶点线性化。 需要如下几个步骤 1.首先找到没有后继的节点。 2.将这个节点加入线性栈中 3.在图中删除这个节点 4.重复步骤1,2,3 因此,首先需要找到后继节点的方法: //寻找图中没有后继节点的点 //具体表现为邻接矩阵中某一列全为0 //此时返回行号,如果找不到返回-1 privateintFindNoSuccessor() { boolisEdge; //循环行 for(inti=0;i { isEdge=false; //循环列,有一个1就跳出循环 for(intj=0;j { if(adjmatrix[i,j]==1) { isEdge=true; break; } } if(! isEdge) { returni; } } return-1; } 此外还需要删除图中点的方法,这个方法不仅需要删除图中对应位置的点,还需要删除邻接矩阵对应的行和列,因此设置了两个辅助方法,见代码。 //删除图中的点 //需要两个操作,分别从数组中删除点 //从邻接矩阵中消去被删点的行和列 privatevoidDelVertex(intvert) { //保证不越界 if(vert<=numVerts-1) { //删除节点 for(inti=vert;i { vertiexes[i]=vertiexes[i+1]; } //删除邻接矩阵的行 for(intj=vert;j { MoveRow(j,numVerts); } //删除邻接矩阵中的列,因为已经删了行,所以少一列 for(intk=vert;k { MoveCol(k,numVerts-1); } //删除后减少一个 numVerts--; } } //辅助方法,移动邻接矩阵中的行 privatevoidMoveRow(introw,intlength) { for(intcol=row;col { adjmatrix[row,col]=adjmatrix[row+1,col]; } } //辅助方法,移动邻接矩阵中的列 privatevoidMoveCol(intcol,intlength) { for(introw=col;row { adjmatrix[row,col]=adjmatrix[row,col+1]; } } 有了这几个方法,就可以按照步骤开始拓扑排序了: //拓扑排序 //找到没有后继节点的节点,删除,加入一个栈,然后输出 publicvoidTopSort() { intorigVerts=numVerts; //存放返回节点的栈 System.Collections.Stackresult=newStack(); while(numVerts>0) { //找到第一个没有后继节点的节点 intcurrVertex=FindNoSuccessor(); if(currVertex==-1) { Console.WriteLine("图为环路图,不能搞拓扑排序"); return; } //如果找到,将其加入返回结果栈 result.Push(vertiexes[currVertex].Data); //然后删除此节点 DelVertex(currVertex); } /*输出排序后的结果*/ Console.Write("拓扑排序的顺序为: "); while(result.Count>0) { Console.Write(result.Pop()+""); } /*输出排序后的结果*/ } 下面,对拓扑排序进行测试,代码如下: staticvoidMain(string[]args) { Graphg=newGraph(); g.AddVertex("A"); g.AddVertex("B"); g.AddVertex("C"); g.AddVertex("D"); g.AddEdge(0,1); g.AddEdge(1,2); g.AddEdge(2,3); g.AddEdge(3,4); g.TopSort(); Console.ReadKey(); } 测试结果: 图的遍历 很多时候,我们需要知道从图中给定点到另一个点是否能走通,比如几个车站之间是否可以连接。 这时我们需要对图进行查找,查找大概可以分为两类,深度优先遍历和广度优先遍历,下面先来看深度优先遍历。 深度优先遍历(Depth-FirstSearch) 深度优先遍历首先从一个点开始,到一条路径结束,然后循环找第二条路径,到结束,依此往复。 首先我们需要一个辅助方法返回给定的点最近一个连接并且未被访问过的序号。 //从邻接矩阵查找给定点第一个相邻且未被访问过的点 //参数v是给定点在邻接矩阵的行 privateintGetAdjUnvisitedVertex(intv) { for(intj=0;j { if(adjmatrix[v,j]==1&&vertiexes[j].IsVisited==false) { returnj; } } return-1; } 下面,就可以进行深度优先遍历了: //深度优先遍历 publicvoidDepthFirstSearch() { //声明一个存储临时结果的栈 System.Collections.Stacks=newStack(); //先访问第一个节点 vertiexes[0].IsVisited=true; DisplayVert(0); s.Push(0); intv; while(s.Count>0) { //获得和当前节点连接的未访问过节点的序号 v=GetAdjUnvisitedVertex((int)s.Peek()); if(v==-1) { s.Pop(); } else { //标记为已经被访问过 vertiexes[v].IsVisited=true; DisplayVert(v); s.Push(v); } } //重置所有节点为未访问过 for(intu=0;u { vertiexes[u].IsVisited=false; } } 广度优先遍历(Breadth-FirstSearch) 广度优先遍历首先遍历层级。 算法如下: //广度优先遍历 publicvoidBreadthFirstSearch() { System.Collections.Queueq=newQueue(); /*首先访问第一个节点*/ vertiexes[0].IsVisited=true; DisplayVert(0); q.Enqueue(0); /*第一个节点访问结束*/ intvert1,vert2; while(q.Count>0) { /*首先访问同层级第一个节点*/ vert1=(int)q.Dequeue(); vert2=GetAdjUnvisitedVertex(vert1); /*结束*/ while(vert2! =-1) { /*首先访问第二个节点*/ vertiexes[vert2].IsVisited=true; DisplayVert(vert2); q.Enqueue(vert2); //寻找邻接的 vert2=GetAdjUnvisitedVertex(vert1); } } //重置所有节点为未访问过 for(intu=0;u { vertiexes[u].IsVisited=false; } } 下面我们来测试深度优先和广度优先遍历: 我们的测试生成一个如下的图: 测试代码: staticvoidMain(string[]args) { Graphg=newGraph(); g.AddVertex("A"); g.AddVertex("B"); g.AddVertex("C"); g.AddVertex("D"); g.AddVertex("E"); g.AddVertex("F"); g.AddVertex("G"); g.AddEdge(0,1); g.AddEdge(0,2); g.AddEdge(1,3); g.AddEdge(2,4); g.AddEdge(3,5); g.AddEdge(4,6); Console.WriteLine("\n深度优先遍历"); g.DepthFirstSearch(); Console.WriteLine("\n广度优先遍历"); g.BreadthFirstSearch(); Console.ReadKey(); } 运行结果:
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- c# 实现 操作
![提示](https://static.bdocx.com/images/bang_tan.gif)