目录
1 基本理论
图结构由节点(Vertex)和边(Edge)构成。
根据连接节点之间的边是否存在方向,可以将图划分为有向图和无向图;比如在一个社交网络中,A关注了B,但是B没有关注A,即A到B的关注是单向的,故社交网络中的关注关系可以使用有向图表示;而A和B是朋友,则他们互为朋友,则就可以使用无向图来表示。根据边上是否有权重,我们可以将图分为有权图和无权图,有权图的边上有具体的权重值;而无权图则仅表示节点之间的链接关系。
故根据是否有权及是否有向,我们可将图划分为无向无权图、无向有权图、有向无权图和有向有权图。下面将从无向无权图开始讲述图的基本概念。
1.1 无向无权图
边:表示两个节点是否相连,若相连则存在边,否则不存在;如上图中节点2和6之间就不存在边。
点相邻:两个节点之间存在边,则称他们是相邻的。
顶点度:与顶点相连的边数,也等于相邻的顶点数;如图1中节点3的度为4,而节点6的度为2
路径:两个节点之间是可达的,如图中我们要从节点1到节点5,可以走的一条路径是1-0-3-2-5
环:一个节点,经过其他节点之后,还能回到自身,则说明存在环;如图中的2-3-4-5-2
自环边:节点可以不经过任何节点回到自己,如图中的节点0
平行边:两节点之间存在多条边相连,如上图中的节点3和节点4之间就存在平行边
简单图:既不存在自环边,也不存在平行边的图,成为简单图;如上图就不是一个简单图
1.2 联通分量与生成树
连通分量:在一个图中,内部相连而外界不相连的子图的个数,即为连通分量;
一个图中可以包含多个连通分量,如图2中,1~6和7-8分别构成两个联通分量;
图论中,树是一种无环连通图,故无环图不一定是树,
连通图的生成树:每个连通图都有生成树
最小生成树:连通图的最小生成树是使用V-1条边,将图中的所有节点连接起来;但是由V-1条边连接的图,如果不是连通图,则就不是图的最小生成树。
严格的来说,由于每个图可能存在多个联通分量,而每个连通分量都存在生成树,故每个图都存在生成森林。
2 代码实现
2.1 邻接矩阵
将文件格式转换为邻接矩阵,第一行第一个数字为顶点的个数,第一列为边的个数;下面的行表示相邻的节点
2.2 C#实现邻接矩阵源码
源码:
class AdjMatrix
{
int vertexCount;
int edgeCount;
int[,] adjMat;
public AdjMatrix(string fileName)
{
try
{
string[] lines = System.IO.File.ReadAllLines(fileName);
vertexCount = int.Parse(lines[0].Split(' ')[0]);
if(vertexCount < 0)
{
throw new Exception("自定义异常信息:文件中节点个数小于0,请检查核实");
}
edgeCount = int.Parse(lines[0].Split(' ')[1]);
if (edgeCount < 0)
{
throw new Exception("自定义异常信息:文件中边个数小于0,请检查核实");
}
adjMat = new int[vertexCount, vertexCount];
for (int i = 0; i < edgeCount; i++)
{
int head = int.Parse(lines[i + 1].Split(' ')[0]);
validateVertex(head);
int tail = int.Parse(lines[i + 1].Split(' ')[1]);
validateVertex(tail);
if(head == tail)
{
throw new Exception("自定义异常信息:存在自环边");
}
if(adjMat[head, tail] == 1)
{
throw new Exception("自定义异常信息:存在平行边");
}
adjMat[head, tail] = 1;
adjMat[tail, head] = 1;
}
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
}
/// <summary>
/// 节点是否有效,若为无效节点抛出异常
/// </summary>
/// <param name="v"></param>
private void validateVertex(int v)