Interface
AddVertex(T data)
AddEdge(int from, int to)
DFS
BFS
MST
TopSort
PrintGraph
using System; using System.Collections.Generic; using System.Linq; namespace TestCase1.TestCase.GraphMatrix { public class Vertex<T> { public T Data { get; set; } public bool Visited { get; set; } public Vertex(T data) { this.Data = data; this.Visited = false; } } public class GraphMatrix<T> { private int GraphSize = 0; private List<Vertex<T>> Vertices { get; set; } private int[,] adjMatrix { get; set; } private int Capacity { get; set; } public GraphMatrix(int capacity) { this.Vertices = new List<Vertex<T>>(); this.Capacity = capacity; this.adjMatrix = new int[capacity, capacity]; for (int i = 0; i < capacity; i++) { for (int j = 0; j < capacity; j++) { this.adjMatrix[i, j] = 0; } } } public void AddVertex(T data) { // ? need check var result = this.Vertices.Where(t => t.Data.Equals(data)); if (result == null || !result.Any()) { this.Vertices.Add(new Vertex<T>(data)); this.GraphSize++; } } public void AddEdge(int from, int to) { if (from >= this.GraphSize || to >= this.GraphSize) { throw new ArgumentException("index is out of graph size!"); } this.adjMatrix[from, to] = 1; this.adjMatrix[to, from] = 1; } public void AddDirectedEdge(int from, int to) { if (from >= this.GraphSize || to >= this.GraphSize) { throw new ArgumentException("index is out of graph size!"); } this.adjMatrix[from, to] = 1; } public void ShowVertex(Vertex<T> ver) { Console.WriteLine("Show vertext = {0}", ver.Data); } public void InitVisit() { foreach (var v in this.Vertices) { v.Visited = false; } } public void PrintGraph() { for (int i = 0; i < this.GraphSize; i++) { Console.WriteLine(); Console.Write("Vertex is {0}: ", this.Vertices[i].Data); for (int j = 0; j < this.GraphSize; j++) { if (this.adjMatrix[i, j] == 1) { Console.Write(this.Vertices[j].Data); Console.Write(" "); } } } } public int FindVertexWithoutSuccssor() { for (int i = 0; i < this.GraphSize; i++) { bool hasSuccessor = false; for (int j = 0; j < this.GraphSize; j++) { if (this.adjMatrix[i, j] == 1) { hasSuccessor = true; break; } } if (!hasSuccessor) { return i; } } return -1; } public void MoveColumn(int column) { for (int row = 0; row < this.GraphSize; row++) { for (int j = column + 1; j < this.GraphSize; j++) { this.adjMatrix[row, j - 1] = this.adjMatrix[row, j]; } } } public void MoveRow(int row) { for (int column = 0; column < this.GraphSize; column++) { for (int j = row + 1; j < this.GraphSize; j++) { this.adjMatrix[j - 1, column] = this.adjMatrix[j, column]; } } } public void RemoveVertex(int index) { this.Vertices.RemoveAt(index); this.GraphSize--; // important here. } public void TopSort() { Stack<Vertex<T>> stack = new Stack<Vertex<T>>(); while (this.GraphSize > 0) { int vertex = FindVertexWithoutSuccssor(); if (vertex == -1) { throw new Exception("The graph has cycle!"); } stack.Push(this.Vertices[vertex]); this.MoveRow(vertex); this.MoveColumn(vertex); this.RemoveVertex(vertex); } while (stack.Count != 0) { var ret = stack.Pop(); Console.WriteLine(ret.Data); } } public void DFS() { Stack<int> stack = new Stack<int>(); // validation if (this.GraphSize == 0) { Console.WriteLine("graph is empty, no op!"); return; } stack.Push(0); this.Vertices[0].Visited = true; ShowVertex(this.Vertices[0]); while (stack.Count != 0) { int index = stack.Peek(); // find next un-visited edge int v = this.GetNextUnVisitedAdjancentNode(index); if (v == -1) { stack.Pop(); } else { this.ShowVertex(this.Vertices[v]); this.Vertices[v].Visited = true; stack.Push(v); } } // reset ALL VISIT flags this.InitVisit(); } public void BFS() { Queue<int> queue = new Queue<int>(); // validation if (this.GraphSize == 0) { return; } // logic queue.Enqueue(0); ShowVertex(this.Vertices[0]); this.Vertices[0].Visited = true; while (queue.Count > 0) { int result = queue.Dequeue(); // find adjacent nodes and enqueue them for (int j = 0; j < this.GraphSize; j++) { if (adjMatrix[result, j] == 1 && this.Vertices[j].Visited == false) { // print all adjacent nodes ShowVertex(this.Vertices[j]); this.Vertices[j].Visited = true; queue.Enqueue(j); } } } // reset this.InitVisit(); } public void MST() { // validation if (this.GraphSize == 0) { return; } // init Stack<int> stack = new Stack<int>(); stack.Push(0); int currentVertex = 0; int vertex = 0; this.Vertices[0].Visited = true; while (stack.Count > 0) { currentVertex = stack.Peek(); vertex = this.GetNextUnVisitedAdjancentNode(currentVertex); if (vertex == -1) { stack.Pop(); } else { this.Vertices[vertex].Visited = true; // print Console.Write(this.Vertices[currentVertex].Data.ToString() + this.Vertices[vertex].Data.ToString()); Console.Write("-> "); stack.Push(vertex); } } // clean up this.InitVisit(); } private int GetNextUnVisitedAdjancentNode(int v) { // validation if (v >= this.GraphSize) { throw new Exception("v is out of graph size!"); } for (int i = 0; i < this.GraphSize; i++) { if (adjMatrix[v, i] == 1 && !this.Vertices[i].Visited) { return i; } } return -1; } public void DepthFirstSearch() { DFSUtil(0); this.InitVisit(); } private void DFSUtil(int vertex) { // validation if (vertex >= this.GraphSize) { throw new ArgumentException("out of graph size!"); } int ver = this.GetNextUnVisitedAdjancentNode(vertex); if (ver == -1) { return; } else { // print current node ShowVertex(this.Vertices[ver]); this.Vertices[ver].Visited = true; DFSUtil(ver); } } } }