我正在处理二叉树。
所以我的数据库中有一个数据库表,每个节点都是最多2个其他节点的父节点。我有一个计划,有效地找到最少的节点(在给定节点下),它是少于2个其他节点的父节点。我正在寻找最开放的位置来换句话说。所以我将其作为广度优先搜索实现。但是我为每个节点调用数据库的方式效率很低。我基本上沿着树走下去,在每个级别上生成一个运行的节点列表,并检查每个节点是否是其他两个节点的父节点。
如果你想看到代码,请点击这里:
# breadth-first search
def build_and_return_parent_id(breadth_list) do
[ {node_id} | tail ] = breadth_list
child_list = fetch_children_id(node_id)
bc_list = tail ++ child_list
case length(child_list) do
x when x > 2 ->
# recursion
build_and_return_parent_id(bc_list)
2 ->
# recursion
build_and_return_parent_id(bc_list)
_ -> node_id
end
end
def fetch_children_id(id) do
Repo.all( from n in Node,
where: n.parent_id == ^id,
order_by: [asc: n.inserted_at],
select: {n.id})
end
end
所以不要这么低效 - 每个节点一个db调用 - 我在想,如何生成一个包含少于两个父节点的所有节点的列表,然后沿着树向下移动,每个级别使用一个db调用以获取该级别上所有节点的列表,然后简单地比较这两个列表。如果两个列表中都有匹配的ID,我发现一个节点下面有一个可用的点。
这是一张图表:
问题是我对sql查询几乎一无所知。我的猜测是,这可以通过桌面上的某种自联接来完成。
node_id | parent_id
----------------------
1 | nil
2 | 1
3 | 1
4 | 2
5 | 2
6 | 3
7 | 4
8 | 5
9 | 6
10 | 3
所以无论如何,我确定这个方法是否有效,但是我似乎无法找到有关用于生成打开列表或级别的sql查询类型的任何信息。名单。
现在我想第二个查询非常简单。因为我们有一个开放列表,所以我们可以使用where-in- [list]子句。我认为第一个是我正在努力的那个。
如果您有任何可以指向或帮助的事情,您可以提供我真的很感激。
答案 0 :(得分:2)
您可以添加列#extra
和depth
并创建索引:
child_count
然后搜索基本上应该是:
create index nodes_depth_1child_idx on nodes(depth) where child_count=1;
您还应该创建可以维护这些值的触发器。这会稍微减慢插入操作,因为插入必须读取父节点select node_id from nodes where child_count=1 order by depth limit 1;
并更新父节点depth
。