基于我所看到的一切,将顶点(或节点-但您要调用它们)连接在一起的标准方法是创建一个包含“从”顶点到“至”顶点的边。表示此连接的方式有几种(adjacency list
,adjacency matrix
,incident matrix
等)。
可以给边缘(和顶点)labels
来赋予边缘身份/价值。也可以给它们一个weight
(可能与label
相同,但是从我所看到的-有所不同)。
使用边缘为adjacency list
的{{1}}实现基本上如下(伪代码):
labels
但是,要确定顶点是否具有带有特定标签的边,则运算变为myGraph.adjacencyList = {
"vertex1": {
"vertex2": "label",
"vertex3": "label",
"vertex4": "anotherLabel"
}
}
-其中O(|D|)
(度)是顶点具有的边数:
|D|
为了进行// pseudo code
const getAdjacenciesConnectedByLabel = (graph, fromVertex, label) => Object.entries(graph.adjacencyList[fromVertex]).reduce((adjacenciesConnectedByLabel, [toVertex, edgeLabel]) => adjacenciesConnectedByLabel.concat(edgeLabel === label ? toVertex : []), []);
// this would then be used as follows:
getAdjacenciesConnectedByLabel(myGraph, 'vertex1', 'label');
// >>> ["vertex2", "vertex3"]
操作(我的目标),我的第一个想法是“翻转”邻接关系的存储方式:
O(1)
但是,现在查找某个顶点是否具有另一个顶点(anotherGraph.adjacencyList = {
"vertex1": {
"label": ["vertex2", "vertex3"],
"anotherLabel": ["vertex4"]
}
}
const getAdjacenciesConnectedByLabel = (graph, fromVertex, label) => graph.adjacencyList[fromVertex][label];
)的边的操作变为isAdjacent
(如果还不差,我实际上并不完全知道如何表示以下函数)以Big O表示法-可能是O(|D|)
,其中O(|D| * |L|)
是每个顶点的标签数):
|L|
我正在尝试找到一种进行两种类型的操作const isAdjacent = (graph, from, to) => Object.values(graph.adjacencyList[from]).reduce(bool, vertexSet) => !bool ? bool : vertexSet.includes(to), false);
// this could be slightly optimized if you were to use a for or while loop which then stopped as soon as a matching "to" vertex was found
// this would then be used as follows:
isAdjacent(anotherGraph, 'vertex1', 'vertex3');
// >>> true
的方法。我唯一的想法是创建另一个“索引”,然后仅跟踪顶点和顶点之间的边。那么邻接表将保留标签,但这似乎不必要地复杂。
如果无法找到一种方法来进行两种类型的操作O(1)
,我想知道建立邻接表的推荐方法(以上两种方法中的哪一种)尝试处理数据关系时,我的操作将是O(1)
。
我想我希望“获得通过标签连接的邻接关系”的操作为O(1)
(即O(1)
看起来像为:adjacencyList
),因为这是一个好方法过滤/检索数据(按它们之间的关系-AKA标签名称)。但是我可能会完全错过这个标记,实际上最好由(vertexFrom, (label, verticesTo))
来存放adjacency list
,如果我需要检查(vertexFrom, (vertexTo, label))
,我会更好必须遍历每个相邻的顶点。
如果有道理。