Home Full Site
자료구조 : 그래프 (Graph)

그래프(Graph)는 노드(꼭지점, Vertex)과 변(Edge)로 구성되어 있는 자료 구조로서 트리와 다르게 사이클(Cycle)을 허용한다. Edge 에 방향을 허용하느냐 마느냐에 따라서 방향이 있는 그래프(Directed Graph), 혹은 방향이 없는 그래프(Undirected Graph)로 나눌 수 있다. 또한 각 변에 가중치(Weight)를 주어 노드와 노드 사이에 숫자로 거리, 비용등의 관계를 표현할 수 있다. 일반적으로 Graph 자료구조는 인접리스트(Adjacency List)나 인접 행렬 (Adjacency Matrix) 등의 방법으로 표현한다. 그래프는 도시간 최단 행로를 구하거나 웹 링크 연결도를 표현하는 등 여러 종류의 자료를 표현하는데 사용될 수 있다.



C#으로 간단한 그래프 구현

.NET Framework은 그래프와 관련된 클래스를 제공하지 않는다. 그래프를 구현하는 한 방식으로 아래 코드는 각 노드마다 인접한 노드들의 리스트를 가지고 있는 인접리스트(Adjacency List)를 사용하고 있다. Graph클래스는 GraphNode들을 갖는 리스트를 기본 필드로 갖고 있으며, 각 GraphNode는 데이타 (혹은 키+데이타) 필드와 인접 노드 리스트를 기본적인 필드로 가지고 있다. GraphNode는 필요에 따라 Weight 배열을 가질 수 있는데, 이는 각 변(Edge)의 가중치를 저장할 필요가 있을 때 사용된다.

예제

// GraphNode 클래스
public class GraphNode<T>
{
    private List<GraphNode<T>> _neighbors;
    private List<int> _weights;

    public T Data { get; set; }

    public GraphNode()
    {                
    }

    public GraphNode(T value)
    {
        this.Data = value;
    }

    public List<GraphNode<T>> Neighbors
    {
        get
        {
            _neighbors = _neighbors ?? new List<GraphNode<T>>();
            return _neighbors;
        }
    }

    public List<int> Weights
    {
        get
        {
            _weights = _weights ?? new List<int>();
            return _weights;
        }
    }
}

// Graph 클래스
public class Graph<T>
{
    private List<GraphNode<T>> _nodeList;

    public Graph()
    {
        _nodeList = new List<GraphNode<T>>();
    }

    public GraphNode<T> AddNode(T data)
    {
        GraphNode<T> n = new GraphNode<T>(data);
        _nodeList.Add(n);
        return n;
    }

    public GraphNode<T> AddNode(GraphNode<T> node)
    {
        _nodeList.Add(node);
        return node;
    }

    public void AddEdge(GraphNode<T> from, GraphNode<T> to, bool oneway=true, int weight=0)
    {            
        from.Neighbors.Add(to);
        from.Weights.Add(weight);
            
        if (!oneway)
        {
            to.Neighbors.Add(from);
            to.Weights.Add(weight);
        }
    }

    internal void DebugPrintLinks()
    {
        foreach (GraphNode<T> graphNode in _nodeList)
        {                
            foreach (var n in graphNode.Neighbors)
            {
                string s = graphNode.Data + " - " + n.Data;
                Console.WriteLine(s);
            }                
        }
    }
}

// Graph 테스트
internal class Program
{
    private static void Main(string[] args)
    {
        Graph<int> g = new Graph<int>();
        var n1 = g.AddNode(10);
        var n2 = g.AddNode(20);
        var n3 = g.AddNode(30);
        var n4 = g.AddNode(40);
        var n5 = g.AddNode(50);

        g.AddEdge(n1, n3);
        g.AddEdge(n2, n4);
        g.AddEdge(n3, n4);
        g.AddEdge(n3, n5);

        g.DebugPrintLinks();
    }
}




© csharpstudy.com