You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中基于节点坐标的两点连通性判断(DFS实现困惑)

解决思路与代码实现

嘿,别担心,新手阶段遇到这种没现成边结构的图问题太正常了!我来一步步帮你搞定~

第一步:从节点数据构建邻接表

DFS的核心是知道每个节点的直接邻居,而你现在只有带坐标的节点,所以首先得根据距离阈值limit生成邻接表——这是一个字典,键是节点ID,值是所有和它直接连通的节点ID列表。

计算两点距离用欧氏距离就行,Python里可以直接用math.hypot(x2-x1, y2-y1)计算,省得自己写平方和开根号的代码,既简洁又不容易出错。

第二步:基于邻接表实现DFS

有了邻接表,DFS就和常规示例逻辑一致了,核心要点:

  • 用集合记录已访问节点,避免无限循环
  • 递归访问当前节点的所有邻居,直到找到目标节点或者遍历完所有可达节点

完整代码示例

import json
import math

class Node:
    def __init__(self, node_id, x, y):
        self.id = node_id
        self.x = x
        self.y = y

def build_adjacency_list(nodes, limit):
    adjacency = {}
    # 先给每个节点初始化空的邻居列表
    for node in nodes:
        adjacency[node.id] = []
    # 遍历所有节点对,判断是否连通
    for i in range(len(nodes)):
        node_a = nodes[i]
        for j in range(i+1, len(nodes)):
            node_b = nodes[j]
            # 计算欧氏距离
            distance = math.hypot(node_b.x - node_a.x, node_b.y - node_a.y)
            if distance <= limit:
                # 互相添加为邻居
                adjacency[node_a.id].append(node_b.id)
                adjacency[node_b.id].append(node_a.id)
    return adjacency

def dfs(current_id, target_id, adjacency, visited):
    # 找到目标节点,直接返回True
    if current_id == target_id:
        return True
    # 标记当前节点为已访问,避免重复遍历
    visited.add(current_id)
    # 递归访问所有未被访问的邻居
    for neighbor_id in adjacency[current_id]:
        if neighbor_id not in visited:
            if dfs(neighbor_id, target_id, adjacency, visited):
                return True
    # 遍历完所有可达节点都没找到目标,返回False
    return False

def are_nodes_connected(start_id, end_id, nodes, limit):
    # 先构建邻接表
    adjacency = build_adjacency_list(nodes, limit)
    # 初始化访问集合
    visited = set()
    # 调用DFS判断连通性
    return dfs(start_id, end_id, adjacency, visited)

# 测试你的JSON示例
if __name__ == "__main__":
    # 模拟JSON解析(假设你已经完成了这一步)
    json_data = '''{
        "limit": 32.0,
        "nodes": [
            {"y": 9.0, "x": 65.0, "id": 0},
            {"y": 44.6, "x": 3.4, "id": 1},
            {"y": 1.5, "x": 98.9, "id": 2},
            {"y": 2.67, "x": 7.0, "id": 3},
            {"y": 3.0, "x": 65.0, "id": 4}
        ]
    }'''
    data = json.loads(json_data)
    # 转换成Node实例集合
    nodes = [Node(node['id'], node['x'], node['y']) for node in data['nodes']]
    limit = data['limit']

    # 测试案例1:节点0和4(直接连通)
    print(f"节点0和4是否连通?{are_nodes_connected(0, 4, nodes, limit)}")  # 输出True
    # 测试案例2:节点0和1(孤立节点,不连通)
    print(f"节点0和1是否连通?{are_nodes_connected(0, 1, nodes, limit)}")  # 输出False
    # 测试案例3:节点1和3(距离超过阈值,不连通)
    print(f"节点1和3是否连通?{are_nodes_connected(1, 3, nodes, limit)}")  # 输出False

关键细节说明

  • 邻接表构建:用两层循环遍历所有节点对(只算i<j的情况),避免重复计算,写法直观易懂,适合新手。如果节点数量特别多,可以考虑空间换时间的优化,但目前这个版本足够应对大部分场景。
  • 访问集合:用set来记录已访问节点,保证每个节点只被处理一次,防止递归陷入循环(比如A和B互相连通的情况)。
  • 递归终止条件:要么找到目标节点立即返回True,要么遍历完所有可达节点后返回False。

如果还有哪个环节没搞懂,随时问我哦!

内容的提问来源于stack exchange,提问作者Skyris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:51:41