在没有递归的情况下找到到达一定深度的所有路径中n元树的所有唯一节点

如何解决在没有递归的情况下找到到达一定深度的所有路径中n元树的所有唯一节点

我正在尝试用Python编写算法,以获取路径到达​​特定深度的树中所有节点的唯一列表。

  • 每个孩子在遍历之前有未知数目的孩子
  • 可以通过可迭代的方式(例如for child in B.get_children())访问子级

例如,请参见此树(应包括星号标记节点):

       A*
       |
     -----
    |     |
    B*    C*
    |     |
    |    ---
    |   |   |
    D*  E   F*
  / | \     | \
 G* H* I*   J* K*
               |
               L

比方说,我试图达到3的深度。我需要一个能够以任意顺序产生序列[G,H,I,J,K,D,F,B,C,A]的函数。

请注意:

  • E(深度不超过3)
  • L(深度超过3)

我觉得有一种方法可以递归获取此列表。类似于:

def iterate_tree(path: List[T],all_nodes: Set[T]):
    if len(path) == 4:
        for node in path:
            if node not in all_nodes:
                all_nodes.add(node)
                yield node
    else:
        for node in path[-1].get_children():
            path = path.copy()
            path.append(node)
            yield from iterate_tree(path,all_nodes)

iterate_tree([A],set())

我不知道上面的方法是否有效,但是我认为可以从中破解。对于(可能不正确的)解决方案,我不满意的是:

  1. 递归:我正在写这个未知的深度。我不要堆栈溢出。
  2. 我真的觉得必须有一种方法可以在不携带set个先前的yielded个节点的情况下进行此操作。
  3. 我必须在每次迭代时复制path的副本,以免弄乱递归的其他分支。

有什么建议吗?

解决方法

对于第1点,您可以使用显式堆栈循环而不是递归。

对于第二点,我不确定保留一组屈服节点是否存在问题。内存很便宜,如果您需要检测重复的内存,那么每次生成树时都要遍历树非常昂贵。

此外,您的实现基于节点哈希性检查唯一性,但是还不清楚节点如何计算其哈希。我假设您为此使用Node.val。如果您基于对象引用进行哈希处理,则“唯一性”似乎毫无意义,因为可以确保节点对象树按身份是唯​​一的。此处的示例并未显示出唯一性的冲突。我的实现假定散列是对象身份(应该是对象身份),并且您可以使用Node.val单独访问唯一性值。

对于第3点,如果您是递归工作,则无需复制路径列表,因为您可以重新访问调用框架并可以在单个列表上追加/弹出。迭代地,您可以在parent_of集旁边保留一个nodes_yielded字典,该集合保留对每个节点的父节点的引用。当我们到达所需深度的节点时,我们可以遍历此字典中的链接来重建路径,而不必担心多次使用nodes_yielded重新访问分支。第二组vals_yielded可用于对收益率实施唯一性。

最后,我真的不知道您的数据结构是什么,因此为了minimal,complete example的利益,我提供了一些适合您的内容。

import collections

def unique_nodes_on_paths_to_depth(root,depth):
    parent_of = {root: None}
    nodes_yielded = set()
    vals_yielded = set()
    stack = [(root,depth)]

    while stack:
        node,depth = stack.pop()

        if depth == 0:
            while node and node not in nodes_yielded:
                if node.val not in vals_yielded:
                    vals_yielded.add(node.val)
                    yield node

                nodes_yielded.add(node)
                node = parent_of[node]
        elif depth > 0:
            for child in node.children:
                parent_of[child] = node
                stack.append((child,depth - 1))

if __name__ == "__main__":
    """
           A*
           |
         -----
        |     |
        B*    C*
        |     |
        |    ---
        |   |   |
        D*  E   F*
      / | \     | \
     G* H* I*   J* K*
                   |
                   L
    """
    Node = collections.namedtuple("Node","val children")
    root = Node("A",(
        Node("B",(
            Node("D",(
                Node("G",()),Node("H",Node("I",)),Node("C",(
            Node("E",Node("F",(
                Node("J",Node("K",(
                    Node("L",))
    ))
    print([x.val for x in unique_nodes_on_paths_to_depth(root,3)])
    #      => ['K','F','C','A','J','I','D','B','H','G'] 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 <select id="xxx"> SELECT di.id, di.name, di.work_type, di.updated... <where> <if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 <property name="dynamic.classpath" value="tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-