Adjacency matrix based Graph

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);
            }
        }
    }
}
原文地址:https://www.cnblogs.com/xuyanran/p/8543209.html