因为后面即将发布的大量有关“图”的算法与源代码都需要用到下面的这些基础数据,为避免大家去下载,特意先发布于此。
一、图(Graph)的基础知识
图(Graph)是一组对象的图示,其中一些对象对通过链接连接。互连对象由称为顶点的点表示,连接顶点的链接称为边。
形式上,图是一对集(V,E),其中V是顶点集,E是连接顶点对的边集。
图形数据结构
数学图可以用数据结构表示。我们可以使用顶点数组和二维边数组来表示图。在继续之前,让我们先熟悉一些重要的术语−
顶点− 图的每个节点都表示为一个顶点。在以下示例中,带标签的圆表示顶点。因此,A到G是顶点。我们可以使用下图所示的数组来表示它们。这里A可以通过索引0来标识。B可以使用索引1等进行识别。
边− 边表示两个顶点之间的路径或两个顶点之间的线。在以下示例中,从A到B、B到C等的线表示边。我们可以使用二维数组来表示数组,如下图所示。这里AB可以表示为第0行第1列的1,BC可以表示为第1行第2列的1,依此类推,其他组合保持为0。
邻接关系− 如果两个节点或顶点通过边相互连接,则它们是相邻的。在以下示例中,B与A相邻,C与B相邻,依此类推。
路径− 路径表示两个顶点之间的边序列。
二、图的基本操作
以下是图形的基本主要操作:
添加顶点 — 将顶点添加到图形中。
添加边 — 在图形的两个顶点之间添加边。
显示顶点 — 显示图形的顶点。
遍历 — 深度优先遍历,宽度优先遍历;
布局 — 图的布局算法
三、图的相关数据
1、节点
using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;namespace Legalsoft.Truffer.Algorithm
{/// <summary>/// 图的结点(坐标)信息/// </summary>public class Node{/// <summary>/// 编号/// </summary>public int Id { get; set; } = 0;/// <summary>/// X坐标/// </summary>public double X { get; set; } = 0.0;/// <summary>/// Y坐标/// </summary>public double Y { get; set; } = 0.0;//public int Weight { get; set; } = 0;/// <summary>/// 默认构造函数/// </summary>public Node() {}public Node(int id) {Id = id;}/// <summary>/// 长度(原点距离)/// </summary>public double Length{get{double len = LengthSquare;if (Math.Abs(len) < float.Epsilon) return 0.0;return Math.Sqrt(len);}}/// <summary>/// 长度平方/// </summary>public double LengthSquare{get{return (X * X) + (Y * Y);}}/// <summary>/// 缩放/// </summary>/// <param name="rate"></param>public void Scale(double rate){X *= rate;Y *= rate;}/// <summary>/// 移动到目的点/// </summary>/// <param name="x"></param>/// <param name="y"></param>public void MoveTo(double x, double y){X = x;Y = y;}/// <summary>/// 移动/// </summary>/// <param name="delta"></param>public void Move(Node delta){this.X += delta.X;this.Y += delta.Y;}/// <summary>/// 加号重载/// </summary>/// <param name="a"></param>/// <param name="b"></param>/// <returns></returns>public static Node operator +(Node a, Node b){Node c = new Node();c.X = a.X + b.X;c.Y = a.Y + b.Y;return c;}/// <summary>/// 减号重载/// </summary>/// <param name="a"></param>/// <param name="b"></param>/// <returns></returns>public static Node operator -(Node a, Node b){Node c = new Node();c.X = a.X - b.X;c.Y = a.Y - b.Y;return c;}}
}
2、边
using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;namespace Legalsoft.Truffer.Algorithm
{public class Edge{/// <summary>/// 起点(第一点)编号/// </summary>public int First { get; set; } = -1;/// <summary>/// 终点(第二点)编号/// </summary>public int Second { get; set; } = -1;/// <summary>/// 权值/// </summary>public int Weight { get; set; } = 0;/// <summary>/// 默认构造函数/// </summary>public Edge(){}/// <summary>/// 两点构造函数/// </summary>/// <param name="f"></param>/// <param name="s"></param>public Edge(int f, int s){First = f;Second = s;}/// <summary>/// 两点及权值构造函数/// </summary>/// <param name="f"></param>/// <param name="s"></param>/// <param name="w"></param>public Edge(int f, int s, int w){First = f;Second = s;Weight = w;}}
}
3、图
using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;namespace Legalsoft.Truffer.Algorithm
{public partial class Graph{/// <summary>/// 是否为有向图?/// </summary>public bool Direction { get; set; } = false;/*/// <summary>/// 节点编码的起始编号0或1/// </summary>public int Node_Index_Start { get; set; } = 0;/// <summary>/// 节点编码的结束编号/// </summary>public int Node_Index_End { get; set; } = 0;*//// <summary>/// 节点总数/// </summary>public int Node_Number { get; set; } = 0;/*/// <summary>/// 连线编码的起始编号0或1/// </summary>public int Edge_Start { get; set; } = 0;*//// <summary>/// 连接线总数/// </summary>public int Edge_Number { get; set; } = 0;/// <summary>/// 节点编码列表/// </summary>public List<Node> Nodes { get; set; } = new List<Node>();/// <summary>/// 连接线列表/// </summary>public List<Edge> Edges { get; set; } = new List<Edge>();/// <summary>/// 节点邻接表/// </summary>public List<int>[] Adjacency { get; set; } = null;/// <summary>/// 邻接矩阵/// </summary>public int[,] Matrix { get; set; } = null;public Graph(){}public Graph(int v, int e = 0, bool direct = false){Direction = direct;Node_Number = v;Edge_Number = e;Adjacency = new List<int>[Node_Number + 1];for (int i = 0; i <= Node_Number; i++){Adjacency[i] = new List<int>();}}public void AddEdge(int a, int b){Adjacency[a].Add(b);if (Direction == false){Adjacency[b].Add(a);}}public void AddEdge(int a, int b, int w){AddEdge(a, b);Edges.Add(new Edge(a, b, w));}public void AddEdge(int idx, int a, int b, int w){Edges[idx] = new Edge(a, b, w);}public void AddNode(int a){if (!Nodes.Exists(t => t.Id == a)){Nodes.Add(new Node(a));}}/// <summary>/// 按三元组构造图数据/// 三元数组为: {source,destination,weight}/// </summary>/// <param name="ternary_array">三元数据</param>public Graph(int[,] ternary_array, bool dir = false){// 有向图?无向图?Direction = dir;Nodes = new List<Node>();Edges = new List<Edge>();Edge_Number = ternary_array.GetLength(0);for (int i = 0; i < ternary_array.GetLength(0); i++){int n1 = ternary_array[i, 0];int n2 = ternary_array[i, 1];int wt = ternary_array[i, 2];AddEdge(n1, n2, wt);}}/// <summary>/// 按关联矩阵数据构建图/// [N x N],元素=0,无连接,>0 有连接线及weight/// </summary>/// <param name="v">节点数</param>/// <param name="e">连边数</param>/// <param name="matrix">关联矩阵</param>public Graph(int[,] matrix){Node_Number = matrix.GetLength(0);Nodes = new List<Node>();Edges = new List<Edge>();Matrix = new int[Node_Number, Node_Number];for (int i = 0; i < Node_Number; i++){for (int j = 0; j < Node_Number; j++){if (matrix[i, j] > 0){AddEdge(i, j, matrix[i, j]);Matrix[i, j] = matrix[i, j];}}}}public Edge FindEdge(int a, int b){foreach (Edge e in Edges){if (e.First == a && e.Second == b){return e;}if (Direction == false){if (e.First == b && e.Second == a){return e;}}}return null;}/// <summary>/// 按邻接表的构造函数/// </summary>/// <param name="adj"></param>public Graph(List<List<int>> adj, bool dir = false){// 有向图?无向图?Direction = dir;Node_Number = adj.Count;Nodes = new List<Node>();Edges = new List<Edge>();// 邻接矩阵Adjacency = adj.ToArray();int idx = 1;foreach (List<int> xu in adj){foreach (int xv in xu){AddEdge(idx, xv);}idx++;}}/// <summary>/// 邻接表 转为 邻接矩阵/// 1 起步!/// </summary>/// <returns></returns>public int[,] AdjacencyMatrix(){if (Matrix == null){Matrix = new int[Node_Number + 1, Node_Number + 1];int idx = 0;foreach (List<int> xu in Adjacency){// 因为 Adjacency[0] 没有被使用!跳过!if (idx > 0){foreach (int xv in xu){Matrix[idx, xv] = 1;}}idx++;}}return Matrix;}}
}
POWER BY TRUFFER.CN