在Python中存储PLC梯形图节点:适合用带循环的多级链表吗?
适合PLC梯形图的Python数据结构方案
针对PLC梯形图的分支、合并、多输入/多邻居等特性,有向无环图(DAG)+ 节点邻接表是比多级链表更适配的通用结构,能解决节点重复出现、遍历去重等核心问题,完全匹配你的需求。
核心节点设计
每个节点类需包含以下核心属性,直接适配梯形图的逻辑特性:
node_id: 唯一标识(区分同一逻辑节点的不同实例,节点相等性仅通过该ID判断,与邻居无关)node_type: 节点类型(如常开触点NO_CONTACT、常闭触点NC_CONTACT、线圈COIL等)left_neighbors: 存储所有输入节点的列表(天然支持多输入分支)right_neighbors: 存储所有输出节点的列表(适配多邻居、分支合并场景)
示例Python实现:
class LadderNode: def __init__(self, node_id, node_type): self.node_id = node_id # 唯一ID,用于判断节点实例唯一性 self.node_type = node_type self.left_neighbors = [] # 所有输入节点集合 self.right_neighbors = [] # 所有输出节点集合 def __eq__(self, other): return isinstance(other, LadderNode) and self.node_id == other.node_id def __hash__(self): return hash(self.node_id)
遍历方案(解决节点去重)
由于约束为仅一个输出节点,从输出节点反向遍历是最高效的方式,结合深度优先搜索(DFS)或广度优先搜索(BFS)+ 集合去重,可轻松获取所有无重复节点:
反向DFS遍历示例
def traverse_backward(start_node): visited = set() stack = [start_node] while stack: current = stack.pop() if current not in visited: visited.add(current) # 此处可加入你的自定义逻辑处理(如提取文本逻辑) # 将所有左邻居加入栈,继续反向遍历 stack.extend(current.left_neighbors) return list(visited)
若需正向遍历(从输入到输出),只需调整为从所有输入节点出发,同样用DFS/BFS+集合去重即可。
需求适配说明
- 相同节点出现在不同位置:通过
node_id唯一标识每个实例,即使逻辑功能相同,不同位置的节点node_id不同,不会被视为同一节点;若需归类同一逻辑的复用节点,可额外添加logic_id属性。 - 支持多输入:
left_neighbors列表可直接存储任意数量的输入节点,完美适配多分支输入场景。 - 节点多左/右邻居:
left_neighbors和right_neighbors均为列表结构,可灵活添加多个邻居,适配分支、合并的复杂链路。 - 分支合并回主链路:合并节点的
left_neighbors只需包含所有分支的末端节点,即可清晰表达合并逻辑。 - 仅一个输出:反向遍历从输出节点出发,可完整覆盖所有关联逻辑节点,避免遗漏,也符合梯形图从输出反推逻辑的常见分析路径。
为什么不推荐多级链表
多级链表存在以下明显局限:
- 无法直观存储多邻居,每个节点只能固定数量的左/右节点,扩展难度大
- 遍历去重需额外处理循环和重复节点,远不如DAG+邻接表结合集合去重的方案成熟
- 分支合并场景下,链表结构会变得异常复杂,邻接表则能保持逻辑清晰
内容的提问来源于stack exchange,提问作者Carl Hidestål
相关产品推荐
相关产品推荐

