1.考考你
说起图这种数据结构,你可能不一定知道;但是我们日常生活中与图相关的应用,你一定都非常熟悉。比如说第一次去一个陌生的地方,你是不是会先看一下地图,然后通过导航到达目标地点;比如说你每天都会打开微信、或者QQ刷朋友圈,看好友动态等。
那么图究竟是一种什么样的数据结构呢?图是一种非线性表的数据结构。说到非线性表的数据结构,还有线性表的数据结构:数组、链表、栈、队列。不知道你都还记得吗?非线性表的数据结构,我们刚刚学完的树也是非线性表的数据结构,对吧。
当然图比树要稍微复杂一些,这一篇中我们主要看图的一些基本概念,和存储就够了。
#考考你:1.你知道图的基本概念有哪些吗?2.你知道如何存储一个图吗?
2.案例
2.1.看图说话
我们先直观的看一个图:无向图、有向图、加权图
2.2.图的基本概念
#图基本概念1.顶点: a.如上图所示,每个图中都有小圆圈,该小圆圈我们称为图的顶点 b.如果是地图,顶点表示地图中的每一个地址 c.如果是微信,顶点表示每一个微信用户 2.边: a.如上图所示,图中的顶点与顶点之间有连线,该连线我们称为图的边,它表示顶点之间的关系 b.如果是地图,边表示两个地址之间的路径 c.如果是微信,边表示两个微信用户存在好友关系 3.度: a.如上图所示,每个顶点都与多个顶点有连线,即有多个边 b.边的个数,我们称为顶点的度 c.如果是微信,顶点的度表示该微信用户有多少个好友 d.在中间有向图中,是带箭头的连线,我们称为方向 e.如果连线箭头指向其它顶点,我们称为出度;如果连线指向顶点本身,我们称为入度 f.关于入度、出度我们以微博为例。微博中有关注与被关注对吧 g.那么入度就表示有多少人关注了你,即你有多少粉丝 h.那么出度表示你关注了别人,比如你关注了某大V 4.无向图 a.如果顶点的连线之间没有箭头,即没有方向,我们称为无向图 5.有向图 a.如果顶点的连线之间有箭头,即有方向,我们称为有向图 6.加权图 a.如上图最后一个图,我们发现顶点的连线上带有数字,我们称该数字为权重 b.那么具体这个权重有什么含义呢? c.你发现QQ有个好友亲密度的功能,就是通过权重实现的了
2.3.图的存储
2.3.1.邻接矩阵
#邻接矩阵1.矩阵你应该不陌生,我们在高数中学过2.你如果想不起来了,那么我再说它就是一个二维数组,你肯定就知道了3.关于图,我们可以通过二维数组来存储(邻接矩阵)4.具体存储方法: a.假设有一个二维数组a[][] b.如果顶点i到顶点j之间有边,我们将a[i][j]记为:1。反之记为:0 c.对于无向图,如果a[i][j] = 1;那么a[j][i]也等于1 d.对于有向图,如果j到i存在连线,那么a[j][i] = 1;否则a[j][i] = 0 e.对于加权图,那么i、j下标对应存储的值,即为权重值。比如a[i][j] = 8 5.下图所示:
邻接矩阵存储图:
2.3.2.邻接表
#邻接表1.邻接矩阵存储图,看起来比较直观,操作起来也比较高效(利用数组下标访问)2.但是邻接矩阵存储图,最大的瑕疵就是浪费存储空间: a.假设存储无向图,相当于浪费了一半的存储空间,对于无向图来说a[i][j] = 1;那么a[j][i]也一定等于1 b.假设存储稀疏图(顶点多,边少的图,我们称为稀疏图)。比如微信有8亿用户,但是常见每个用户的好友也就几百个,对吧 3.因此有了更优化,更节省存储空间的存储方式:邻接表 a.邻接表的存储方式,长得非常像一个散列表,或者说它就是散列表 b.我们直接画一个图,你就知道了 c.为了看起来直观好理解,我们画上图中的有向图的邻接表存储4.对比邻接表与邻接矩阵存储,我们发现邻接表存储图,节省了不少存储空间5.但是我们也说世间万物是平衡的(此消彼长),或者说是公平的6.邻接表虽然节省了存储空间,但是操作起来需要消耗更多的时间,因为遍历链表要比访问数组耗时的多7.当然在实际应用中,我们可以根据需要来选择邻接矩阵,或者邻接表来存储图
邻接表存储图: