图的深度优先和广度优先算法。。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace 数据结构 { public class Program { public class MatrixGraph { public string[] DingDian;//保存顶点信息 public int[,] edges;//保存边信息 public bool[] isTrav; public int vertexNum;//顶点数量 public int edgeNum;//边数量 public int graghType;//图类型 //构造函数,初始化变量 public MatrixGraph(int vertexNum, int edgeNum, int graphType1) { this.vertexNum = vertexNum; this.edgeNum = edgeNum; this.graghType = graphType1; DingDian = new string[vertexNum]; edges = new int[vertexNum, vertexNum]; isTrav = new bool[vertexNum]; } } public static MatrixGraph CreateMatrixGraph() { Console.WriteLine("请输入图的顶点个数,边个数,是否为无向图,用0,1表示"); var initData = Console.ReadLine().Split(',').Select(i => int.Parse(i)).ToList(); //对象生成时,调用构造函数 MatrixGraph graph = new MatrixGraph(initData[0], initData[1], initData[2]); Console.WriteLine("请输入各顶点信息:"); for (int i = 0; i < graph.vertexNum; i++) { Console.Write(" 第"+(i+1)+"个顶点为:"); var single = Console.ReadLine(); //顶点信息加入到集合中 graph.DingDian[i]= single; } Console.WriteLine("请输入构成两个顶点的边和权值,以逗号隔开: "); for (int i = 0; i < graph.edgeNum; i++) { Console.WriteLine("第"+(i+1)+"条边: "); initData=Console.ReadLine().Split(',').Select(j=>int.Parse(j)).ToList(); int start=initData[0]; int end=initData[1]; int weight = initData[2]; graph.edges[start - 1, end - 1] = weight; //判断是否为无向图 if(graph.graghType==1) graph.edges[end - 1, start - 1] = weight; }//for return graph; } #region 广度优先 public static void BFSTraverse(MatrixGraph graph) { //访问标记默认初始化 for (int i = 0; i < graph.vertexNum; i++) graph.isTrav[i] = false; for (int i = 0; i < graph.vertexNum; i++) if (!graph.isTrav[i]) BFSM(ref graph,i); } public static void BFSM(ref MatrixGraph graph,int curvertex) { Queue<int> queue = new Queue<int>(); queue.Enqueue(curvertex); Console.WriteLine("->" + graph.DingDian[curvertex]); graph.isTrav[curvertex] = true; ///当有节点入队列后,count应该不为空 //广度优先设计的关键: while (queue.Count != 0) { var temp = queue.Dequeue();//此顶点出队列 //然后取匹配其邻接点的值 for (int i = 0; i < graph.vertexNum; i++) { if (!graph.isTrav[i] && graph.edges[temp, i] != 0) { Console.WriteLine("->" + graph.DingDian[i]); graph.isTrav[i] = true; queue.Enqueue(i);//为方便下一层的输出 } } } } #endregion #region 深度优先 //又一次用到了递归的算法,你应该很熟悉了 public static void DFSTraverse(MatrixGraph graph) { //访问标记默认初始化 for (int i = 0; i < graph.vertexNum; i++) graph.isTrav[i] = false; for (int i = 0; i < graph.vertexNum; i++) if (!graph.isTrav[i]) DFSM(ref graph, i); } public static void DFSM(ref MatrixGraph graph, int curvertex) { //Queue<int> queue = new Queue<int>(); //queue.Enqueue(curvertex); Console.WriteLine("->" + graph.DingDian[curvertex]); graph.isTrav[curvertex] = true; //深度优先设计的关键:递归算法 for (int i = 0; i < graph.vertexNum; i++) { if (!graph.isTrav[i] && graph.edges[curvertex, i] != 0) { DFSM(ref graph,i); } } } #endregion public static void Main(string[] args) { MatrixGraph graph= CreateMatrixGraph(); Console.WriteLine("广度优先输出为:"); BFSTraverse(graph); Console.WriteLine("深度优先输出为:"); DFSTraverse(graph); Console.ReadLine(); } } }
最小生成树:(prim算法)
算法思想:
假设N=(V,{E})是联通网,TE是N上最小生成树中边的集合。算法从U={u0}(u0属于v),TE={}开始,重复执行下述操作:在所有u属于U,v属于V-U的边(u,v)属于E中找一条代价最小的边(u0,v0)并入集合TE,同时v0并入U,直至U=V为止,此时TE必有n-1条边,则T(V,{TE})为最小生成树。。。
#region prim算法获取最小生成树 public void Prim(MatrixGraph graph,out int sum) { //已访问过的标志 int used = 0; //非邻接顶点标志 int noadj = -1; //定义一个输出总权值的变量 sum = 0; //临时数组,用于保存邻结点的权值 int[] weight = new int[graph.vertexNum]; //临时数组,用于保存顶点信息 int[] tempvertex = new int[graph.vertexNum]; //取出第一个顶点和其他顶点之间的边的权值 for (int i = 1; i < graph.vertexNum; i++) { weight[i] = graph.edges[0, i]; //如果权重等于0则说明v1与该邻接点没有边 if (weight[i] == short.MaxValue) tempvertex[i] = noadj; else tempvertex[i] = int.Parse(graph.DingDian[0]); } //从集合V中取出V1节点,只需要将此节点设置为以访问过,weight为0 var index = tempvertex[0] = used; var min = weight[0] = short.MaxValue; //在V的邻接点中找权值最小的结点 for (int i = 1; i < graph.vertexNum; i++) { index = i; min = short.MaxValue; for (int j= 1; j < graph.vertexNum; j++) { if (weight[j] < min && tempvertex[j] != 0) { min = weight[j]; index = j; } } sum += min; Console.Write("({0},{1})",tempvertex[index],graph.DingDian[index]); //将取得的最小结点标识为已访问 weight[index] = short.MaxValue; tempvertex[index] = 0; //从最新的结点出发,将此结点的weight比较赋值 for (int j = 0; j < graph.vertexNum; j++) { if (graph.edges[index, j] < weight[j] && tempvertex[j] != used) { weight[j] = graph.edges[index, j]; tempvertex[j] = int.Parse(graph.DingDian[index]); } } } } #endregion
最短路径:
看书的算法思想,对哪个例题很清楚怎么分析,对代码还是有点呛,虽然思想也知道,但实现。。难道这样的我只适合考试。。。这就悲剧了,不要这样。。。