Graph.cs
Home
/
YED /
Graph.Simple /
Entities /
Graph.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Graph.Simple.Entities.Base;
using Graph.Simple.Entities.Internal;
namespace Graph.Simple.Entities
{
public class Graph
{
#region
/// <summary>
/// Коллекция вершин
/// key - ID
/// value - вершина графа
/// </summary>
private Dictionary<int, GraphNode> _Nodes;
private Dictionary<int, Node> __Nodes;
public IReadOnlyDictionary<int, Node> Nodes => __Nodes;
/// <summary>
/// Коллекция ребер
/// key - ID
/// value - Ребро
/// </summary>
private Dictionary<int, GraphEdge> _Edges;
private Dictionary<int, Edge> __Edges;// { private set; get; }
public IReadOnlyDictionary<int, Edge> Edges => __Edges;
private int _MaxNodeID = -1;
private int GetNextNodeID => ++_MaxNodeID;
private int _MaxEdgeID = -1;
private int GetNextEdgeID => ++_MaxEdgeID;
#endregion
private void Init()
{
_Nodes = new Dictionary<int, GraphNode>();
__Nodes = new Dictionary<int, Node>();
_Edges = new Dictionary<int, GraphEdge>();
__Edges = new Dictionary<int, Edge>();
}
public Graph()
{
Init();
}
#region
/// <summary>
/// Метод проверяет принадлежат ли данные элементы графу
/// </summary>
/// <param name="elements"></param>
/// <returns></returns>
public bool ContainsElements(params BaseGraphUnit[] elements)
{
foreach (var elem in elements)
{
if (elem == null)
return false;
if (elem.Graph != this)
return false;
}
return true;
}
public Node AddNode()
{
var NewNode = new GraphNode(GetNextNodeID, this);
_Nodes.Add(NewNode.ID, NewNode);
__Nodes.Add(NewNode.ID, NewNode);
return NewNode;
}
public void RemoveNode(Node node, bool WithEdge = false)
{
if (!ContainsElements(node))
throw new Exception("_Graph.RemoveNode | _Graph not contains this node");
GraphNode graphNode = node as GraphNode;
if (!WithEdge && graphNode.Inputs.Count != 0)
throw new Exception("_Graph.RemoveNode | Node contact with edge(s), but WithEdge set false");
while (graphNode.Outputs.Count != 0)
{
RemoveEdge(graphNode.Outputs.First());
}
while (graphNode.Inputs.Count != 0)
{
RemoveEdge(graphNode.Inputs.First());
}
_Nodes.Remove(node.ID);
__Nodes.Remove(node.ID);
}
/// <summary>
/// Добавить ребро
/// </summary>
/// <param name="node_start">Начало</param>
/// <param name="node_end">Окончание</param>
/// <param name="Bidir">Создать двунаправленное</param>
/// <param name="weight">Вес</param>
/// <returns></returns>
public Edge AddEdge(Node node_start, Node node_end, float widht = 1)
{
if (!ContainsElements(node_start, node_end))
throw new Exception("_Graph.AddEdge | _Graph not contains node_start or/and node_end");
if (/*!UseCicleEdge &&*/ node_start == node_end)
throw new Exception("_Graph.AddEdge | node_start == node_end and UseCicleEdge == false");
var graphnode_start = node_start as GraphNode;
var graphnode_end = node_end as GraphNode;
if (/*UseMultiEdge &&*/ graphnode_start.Outputs.FirstOrDefault(e => e.End == node_end) != null
|| (graphnode_start.Inputs.FirstOrDefault(e => e.Start == node_end) != null))
throw new Exception("_Graph.AddEdge | Edge already exists (maybe bidir <->), if change remove and create");
GraphEdge NewEdge = null;
if (widht < 0)
throw new Exception();
NewEdge = new GraphEdge(GetNextEdgeID, this, node_start, node_end)
{
Weight = widht
};
graphnode_start.Outputs.Add(NewEdge);
graphnode_end.Inputs.Add(NewEdge);
_Edges.Add(NewEdge.ID, NewEdge);
__Edges.Add(NewEdge.ID, NewEdge);
return NewEdge;
}
/// <summary>
/// Удаляет ребро и обратное ему
/// </summary>
/// <param name="edge"></param>
public void RemoveEdge(Edge edge)
{
if (!ContainsElements(edge))
throw new Exception("");
((GraphNode)edge.Start).Outputs.Remove(edge);
((GraphNode)edge.End).Inputs.Remove(edge);
_Edges.Remove(edge.ID);
__Edges.Remove(edge.ID);
}
public Edge GetEdge(Node node1, Node node2)
{
if (!ContainsElements(node1, node2))
throw new Exception("Graph.GetEdge | graph not contains nodes");
return Edges.Values.FirstOrDefault(e => e.Start.ID == node1.ID && e.End.ID == node2.ID);
}
#endregion
#region
public void AllClear()
{
_Edges.Clear();
__Edges.Clear();
_MaxEdgeID = -1;
_Nodes.Clear();
__Nodes.Clear();
_MaxNodeID = -1;
}
#endregion
}
}