程序根据网上的例子(具体哪位老哥写的忘记了。。)修改,只修改了最后“获取堆栈当前顶部值的下一个连通点”的功能,在此处穿插了对闭环的判断,并输出
// 检查闭环情况
if (thestack.Contains(j) && thestack.Count > 2) {
List<Object> stackValues = new List<Object>(thestack.ToArray());
// 将堆栈转为list后,top的位置是0,所以应该从大向小遍历
for (int i = stackValues.Count - 1; i > 1; i--) {
if (stackValues[i].Equals(j)) {
// 从当前i递减直到stackValues的top
string res = "形成闭环:";
for (int t = i; t >= 0; t--) {
res += vertexList[(int) stackValues[t]] + ",";
}
Console.WriteLine(res);
break;
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
namespace math
{
class Program
{
static void Main(string[] args)
{
Graph graph = new Graph();
graph.addVertex('A');
graph.addVertex('B');
graph.addVertex('C');
graph.addVertex('D');
graph.addVertex('E');
graph.addVertex('F');
// graph.addVertex('G');
// graph.addVertex('H');
graph.addEdge('A', 'B');
graph.addEdge('B', 'C');
graph.addEdge('C', 'A');
graph.addEdge('A', 'D');
graph.addEdge('D', 'E');
graph.addEdge('E', 'F');
graph.addEdge('F', 'D');
// graph.addEdge('B', 'D');
// graph.addEdge('B', 'E');
// graph.addEdge('E', 'H');
// graph.addEdge('D', 'H');
// graph.addEdge('A', 'C');
// graph.addEdge('C', 'F');
// graph.addEdge('F', 'G');
// graph.addEdge('C', 'G');
Console.WriteLine("深度遍历寻找环结果:");
graph.dfs();
Console.WriteLine();
}
}
class Vertex
{
public Vertex(char label)
{
_label = label;
wasVisited = false;
}
public char _label;
public bool wasVisited;
public override string ToString()
{
return _label.ToString();
}
}
class Graph
{
private static int flag = 1;
private int max_vertexs = 20; //最大顶点数
private Vertex[] vertexList;
private int[,] adjMat;
private int countVertexs;
private Stack thestack;
public Graph()
{
vertexList = new Vertex[max_vertexs];
adjMat = new int[max_vertexs, max_vertexs];
countVertexs = 0;
for (int j = 0; j < max_vertexs; j++)
for (int k = 0; k < max_vertexs; k++)
adjMat[j, k] = 0;
thestack = new Stack(max_vertexs);
}
//初始添加点数
public void addVertex(char label)
{
vertexList[countVertexs++] = new Vertex(label);
}
public void addEdge(int start, int end)
{
adjMat[start, end] = 1;
adjMat[end, start] = 1;
}
public void addEdge(char startV, char endV)
{
int start = -1, end = -1;
for (int i = 0; i < countVertexs; i++) {
if (startV == vertexList[i]._label) start = i;
if (endV == vertexList[i]._label) end = i;
}
if (start == -1) Console.WriteLine("顶点{0}不存在", startV);
if (end == -1) Console.WriteLine("顶点{0}不存在", endV);
//权值默认为1
adjMat[start, end] = 1;
adjMat[end, start] = 1;
}
//显示字符
public void displayVertex(int v)
{
// if (flag == 1) {
// Console.Write(vertexList[v]._label);
// }
// else {
// Console.Write("," + vertexList[v]._label);
// }
//
// flag++;
}
//深度优先遍历
public void dfs()
{
vertexList[0].wasVisited = true;
displayVertex(0);
thestack.Push(0);
//遍历结点
while (thestack.Count != 0) {
//从第v个顶点出发递归地深度优先遍历图 (读取栈里的第一个元素,但是不出栈)
int v = getAdjUnvisitedVertex(Int32.Parse(thestack.Peek().ToString()));
if (v == -1)
//元素出栈
thestack.Pop();
else {
vertexList[v].wasVisited = true;
displayVertex(v);
//元素进栈
thestack.Push(v);
}
}
//初始化所有的顶点状态为未被访问
for (int j = 0; j < countVertexs; j++)
vertexList[j].wasVisited = false;
}
/**
* 获得本vertex的下一个可访问的点
* 此处可以做环检测
* 如果要检测的下一帧存在在堆栈中,且不是top的上一个连接点,那么成立
*/
public int getAdjUnvisitedVertex(int v)
{
for (int j = 0; j < countVertexs; j++) {
if (adjMat[v, j] == 1) {
// 检查闭环情况
if (thestack.Contains(j) && thestack.Count > 2) {
List<Object> stackValues = new List<Object>(thestack.ToArray());
// 将堆栈转为list后,top的位置是0,所以应该从大向小遍历
for (int i = stackValues.Count - 1; i > 1; i--) {
if (stackValues[i].Equals(j)) {
// 从当前i递减直到stackValues的top
string res = "形成闭环:";
for (int t = i; t >= 0; t--) {
res += vertexList[(int) stackValues[t]] + ",";
}
Console.WriteLine(res);
break;
}
}
}
if (vertexList[j].wasVisited == false) {
return j;
}
}
}
return -1;
}
}
}
运行结果 - 图中例子存在两个闭环,此处已识别出来
网友评论