映射数据的两种常见结构是集合和图。实现一个图来映射资源的最大风险是在图中可能有环(环指的是图的一个顶点有多条路径指向另一个顶点,这就意味着遍历图是个无止境的操作)。
——《云原生基础架构.保持资源映射简单》
前言
线性结构中,除首节点没有前驱、末节点没有后继外,一个节点只有唯一的直接前驱和唯一的直接后继;树结构中,除根节点没有前驱节点外,其余的每个节点只有唯一的一个前驱(双亲)节点和多个后继(子树)节点;而在图中,任意节点间都可能有直接关系,也就是说图中一个节点的前驱和后继的数目是不限的。
图的定义
G=(V,E)
V代表图中顶点的非空有限集合,E是图中边的有限集合。
1)有向图。图中每条边都是有方向,记作<vi,vj>,表示从vi到vj有一条有向边;vi称作弧尾,vj称作弧头;
2)无向图。图中每条边都无方向,记作(vi,vj);
3)完全图。一个无向图具有n个顶点,而每个顶点与其它n-1个顶点之间都有边,则称之为无向完全图,此时其共有n(n-1)/2条边。同理n个顶点的有向完全图中边数为n(n-1),因为有向完全图每两个不同顶点之间都有两条方向相反的边;
注:任何一个顶点都可以被看作第一个顶点,巴特为了计算,给图中每个顶点赋一个序号值。
图的存储结构
1)邻接矩阵表示法
图的邻接矩阵表示法是指用一个矩阵来表示图中顶点之间的关系(相连为1,不相连为0)。对于n个顶点的图G=(V,E),其邻接矩阵是个n阶方阵:
有向图及其邻接矩阵:
A=
无向图及其邻接矩阵
B=
2)邻接链表表示法
邻接链表表示法指的是为图的每个顶点建立一个单链表
图的遍历
基于图的每个顶点都可能与其余顶点相连,所以在遍历了某个顶点之后很可能会沿着某路径回到该顶点,这就造成了不必要的重复,那么为了避免对顶点进行重复遍历,在图的遍历过程中必须标记每个已访问过的顶点。
1,深度优先搜索(DFS)
2,广度优先搜索(BFS)
1)一度关系胜过二度关系,广度优先搜索找到的是最短的路径。一个形象例子就是你向朋友借钱,一般从关系最近的关系网开始,一旦这一层借到钱了,借钱活动结束(当然后面你要还);而一旦你的就近朋友没钱借给你,关系铁的会从他自己的朋友那里帮你筹措,也就是说你借到的钱是你朋友的朋友的钱。
算法实现(java):
public class BreadthFirstSearch { private static Map<String, List<String>> graph = new HashMap<>(); private static boolean search(String name) { Queue<String> searchQueue = new ArrayDeque<>(graph.get(name)); // This list is how you keep track of which people you've searched before. List<String> searched = new ArrayList<>(); while (!searchQueue.isEmpty()) { String person = searchQueue.poll(); // Only search this person if you haven't already searched them if (!searched.contains(person)) { if (person_is_seller(person)) { System.out.println(person + " is a mango seller!"); return true; } else { searchQueue.addAll(graph.get(person)); // Marks this person as searched searched.add(person); } } } return false; } private static boolean person_is_seller(String name) { return name.endsWith("m"); } public static void main(String[] args) { graph.put("you", Arrays.asList("alice", "bob", "claire")); graph.put("bob", Arrays.asList("anuj", "peggy")); graph.put("alice", Arrays.asList("peggy")); graph.put("claire", Arrays.asList("thom", "jonny")); graph.put("anuj", Collections.emptyList()); graph.put("peggy", Collections.emptyList()); graph.put("thom", Collections.emptyList()); graph.put("jonny", Collections.emptyList()); search("you"); } }