图的表示:如何存储微博、微信等社交网络中的好友关系?
图的理解(Graph)
非线性表结构,树中的元素称为节点,图中的元素叫做顶点,图中的各个顶点都可以与任意其他顶点建立连接关系,这种建立的关系叫做边
把微信中的每个用户都看作一个顶点,两个用户之间互加好友,就在两者之间建立一个边,其中,每个用户有多少好友,对应在图中,就叫做顶点的度,就是跟顶点连接的边的条数
而微博更复杂,允许单向关注,如果A关注了B,就是一条从A到B的箭头的边,表示边的方向,这种叫有向图,没有方向的图叫做无向图
无向图中有表示一个顶点多少条边的度的概念,有向图中,把度分为入度(In-degree)和出度(Out-degree)顶点的入度,表示有多少条边指向这个顶点;顶点的出度,表示有多少条边以这个顶点为起点指向其他顶点的,以微博为例,入度表示有多少粉丝
QQ中亲密度怎么记录的?
在带权图中,每条边都有一个权重(weight),这个权重可以表示QQ亲密度
邻接矩阵存储方法
图的最直观的存储方式
邻接矩阵的底层依赖一个二维数组,对于无向图来说,如果顶点i和顶点j之间有边,将 和 ,都标记为1,对于有向图来说,顶点I和顶点J之间,有一条箭头从I指向J的边,将 标记为1,同理,J指向I,将 标记为1,用邻接矩阵表示一个图,比较浪费存储空间
对于无向图,如果 = 1,那么 =1,实际上我们存储一个即可,所以无向图的二维数组中,我们将其用对角线划分为上下两部分,只需要利用上面或者下面这样一般的空间足够了
如果存储的是稀疏图,即顶点很多,但每个顶点的边并不多,邻接矩阵的存储方法更加浪费了
但是利用邻接矩阵存储图,可以将很多图的运算转化成矩阵之间的运算,比如求解最短路径时候,利用矩阵循环相称若干次得到结果
邻接表存储方法
每个顶点对应一条链表,链表中存储的是与这个顶点相连接的其他顶点,有向图的邻接表存储方式,每个顶点对应的链表里面,存储的是指向的顶点
使用起来比较耗时间
可以将链表换成更加高效的数据结构,比如平衡二叉查找树
我们可以选用红黑树,可以更加快速的查找两个顶点之间是否存在边
如何存储微博、微信等社交网络中的好友关系?
微博是有向图,微信是无向图
针对微博,支持操作:
- 判断用户A是否关注B
- 判断用户A是否是用户B的粉丝
- 用户A关注用户B
- 用户A取关B
- 根据用户名称首字母排序,分页获取用户的粉丝列表
- 根据用户名称首字母排序,分页获取用户的关注列表
采用邻接表存储图,更是一个逆邻接表,邻接表中存储了用户的关注关系,逆邻接表中存储的是用户的被关注关系,对应图中,邻接表中,每个顶点的链表中存储的是这个顶点指向的顶点,逆邻接表中,每个顶点的链表中存储的是指向这个顶点的顶点,如果查找某个用户关注了哪些用户,可以在邻接表中查找,如果查找某个用户被那些用户关注,从逆邻接表中查找
需要按照用户名称的首字母排序,分页来获取用户的粉丝列表或者关注列表,用跳表,跳表插入、删除、查找非常高效,跳表中存储的数据是有序的
但这只能是小规模的几万、几十万用户,上亿用户得用哈希算法等数据分片方式,将邻接表存储在不同机器上。
一个机器存储顶点1,2,3的邻接表和逆邻接表,机器2存储顶点4,5的邻接表和逆邻接表,当药查询顶点与顶点关系时候,利用同样的哈希算法,定位顶点所在机器,再在响应的机器上查找
1.怎么存储微信这样的无向图?
使用邻接表的方式存世每个人对应的好友列表,为了支持快速查找,可以用红黑树存储