我的数据结构是一个带有节点和边的无向图(可能是密集的)。节点I和J之间的边缘将具有与之关联的附加数据,并且我希望能够在查询时唯一地识别该边缘并且能够快速确定I和J之间的边缘是否存在。
我决定使用两个表来完成此任务:
Table Nodes
-----------
node_id PK
...
(additional fields)
Table Edges
-----------
nodes_hash(node_id, node_id) PK
edge_thickness
...
(additional fields)
其中每个边的主键将由一个带有两个节点ID的散列函数nodes_hash(node_id, node_id)
计算。
我的问题:
答案 0 :(得分:2)
你没有理由需要将边缘编码为哈希:确保没有重复是一个简单的唯一约束。
虽然有计算哈希的方法(创建路径枚举字符串,并计算其MD5哈希或沿着这些行的某些东西),但是存储哈希没有价值,也没有使用路径枚举方案来存储图表数据本身。路径枚举的工作方式与文件系统中的完全相同,存储类似/a/b/c
(如果按节点ID枚举)或1.2.1.5
(如果按边序列枚举)。
对于您的特定用例,我将使用公共邻接列表表设置(除非树中的其他操作调用更专业的数据结构,例如节点集或路径/边缘枚举)。在此结构中,顶级节点具有PARENT_ID = NULL
:
CREATE TABLE NODES(
NODE_ID INT NOT NULL,
-- OTHER NODE ATTRIBUTES
PRIMARY KEY (NODE_ID)
);
CREATE TABLE EDGES(
NODE_ID INT NOT NULL,
PARENT_ID INT,
EDGE_WEIGHT INT NOT NULL,
-- OTHER EDGE ATTRIBUTES
FOREIGN KEY (NODE_ID) REFERENCES NODES(NODE_ID),
FOREIGN KEY (PARENT_ID) REFERENCES NODES(NODE_ID),
CHECK (PARENT_ID <> NODE_ID), -- This avoids simple cycles
CONSTRAINT UNIQ_EDGE UNIQUE (NODE_ID,PARENT_ID) -- This avoids duplicate edges
);
答案 1 :(得分:0)
为什么要使用哈希函数来生成这样的密钥?
我会为节点提供一个整数主键(节点ID)。
我会有一个边的整数主键(边ID)。
然后,我会在边缘表中为每个节点添加两列,并使用外键关系返回节点表。
我可以很容易地想到使用哈希函数的两个缺点。首先,你可能会发生碰撞。事实上,如果所有内容都存储为整数,那么 只会根据鸽子原则进行碰撞。
其次,无论如何都需要存储节点ID。几乎我能想到的任何图形问题都需要知道边缘连接的节点。
您将处理无向图是以下约束/触发器:
(1)添加一个约束/触发器node1&lt;节点2(或者&lt; =如果允许自连接)。
(2)在node1,node2上添加唯一索引。
(3)添加一个插入前触发器,以确保对于任意值,node1获得较小的值,node2获得较大的值。
在Oracle中,您可以通过在最少(node1,node2)和最大(node1,node)上使用基于函数的索引来组合这些。