玩转图论算法C#版笔记01:图的基本概念、邻接矩阵与邻接表

本文介绍了图的基本概念,包括无向无权图的定义和性质,如顶点度、路径和环。接着探讨了联通分量与生成树,并讨论了邻接矩阵和邻接表的实现,包括C#源码,以及稀疏图与稠密图的区别。此外,还对比了LinkedList和红黑树TreeSet在邻接表实现中的优缺点。
摘要由CSDN通过智能技术生成

目录

1 基本理论

1.1 无向无权图

1.2 联通分量与生成树

2 代码实现

2.1 邻接矩阵

2.2 C#实现邻接矩阵源码

2.3 稀疏图与稠密图

3 邻接表及其实现

3.1 LinkedList的实现

3.2  红黑树TreeSet

3.3 邻接表与邻接矩阵建图的复杂度分析

附录:基于HashSet的实现


1 基本理论

图结构由节点(Vertex)和边(Edge)构成。

根据连接节点之间的边是否存在方向,可以将图划分为有向图和无向图;比如在一个社交网络中,A关注了B,但是B没有关注A,即A到B的关注是单向的,故社交网络中的关注关系可以使用有向图表示;而A和B是朋友,则他们互为朋友,则就可以使用无向图来表示。根据边上是否有权重,我们可以将图分为有权图和无权图,有权图的边上有具体的权重值;而无权图则仅表示节点之间的链接关系。

故根据是否有权及是否有向,我们可将图划分为无向无权图、无向有权图、有向无权图和有向有权图。下面将从无向无权图开始讲述图的基本概念。

1.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 连通图相关的概念

一个图中可以包含多个连通分量,如图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)
   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小薛引路

喜欢的读者,可以打赏鼓励一下

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值