r - 在 R 中生成由节点函数递归定义的 K-Nary 树

标签 r recursion tree traversal

如何生成一棵具有未知数量节点的树,每个节点都有未知且不同数量的子节点,条件是给定父节点的子节点列表是由某些 fun(parent )?请注意,我使用 cran 中的库(data.tree)来制作我的树层次结构。

树总是以给定父向量定义的节点开始。节点数量总是有限的。每个节点的长度都与根节点相同。

我尝试从上下文中提出一般意义上的问题,但它太笼统,无法提供明确的反馈。因此,这是目前不完全存在的脚本:

require(data.tree)
#also requires Generating Scripts (link at bottom) to run
# Helper function to insert nodes as children of parents with unique names
i=1
assn <- function(child,parentvarname){
    child<-paste(child,collapse=" ")
    nam <- paste("v", i, sep = "")

    # assign node to variable called vi  
    # and make the tree global so it can be seen outside the function
    assign(nam, parentvarname$AddChild(child),envir = .GlobalEnv) 
    noquote(nam)->a
    i+1
    a          #output the child variable name vi for the sake of recursion
}

cdrtree<- function(root){
    #assign root
    v0 <- Node$new(root)  #assign root to the root of the tree
    node<-root             #rename variable for clarity in next step
    kidparentname<-v0      #recursion starts at v0

    have.kids<-function(node){   #this is unfortunately asexual reproduction...
                for(pointer in cdrpointers(node)){ #A variable number of pointers are
                    #used to determine the next node(s) if any with function cdrmove

                    cdrmove(node,pointer)->newkid #make a child
                    assn(newkid,kidparentname) #enter this node in the tree hierarchy

                    #get the name of newkid for next iteration and write name to tree
                    kidparentname<-assn(newkid,kidparentname)
                    node<-newkid    #rename node variable for the next iteration
                    have.kids(newkid)  #recurse, likely the problem is here
                }

    return(v0) #return the tree (if the code works...)
        }
}

在可能的根节点上运行脚本会产生奇怪的结果:

> cdrtree(c(1,-2,3))
> cdrtree(c(1,-2,3))->a
> a
function(node){   #this is unfortunately asexual reproduction...
                for(pointer in cdrpointers(node)){ #A variable number of pointers are
                    ... #all code as written above ...
}
<environment: 0x00000000330ee348>

如果您想要一个真正的工作示例,您可以从 here 获取并获取“Generate Scripts.R”。并使用 1:n 的任何有符号排列运行它,其中 n>2 作为参数,类似于我的示例。

更清楚地说,根节点为 c(1,-2,3) 的树假设看起来像这样:

A tree with root node c(1,-2,3).

最佳答案

我认为您的功能没有按预期工作。例如,使用您的起始值,

lapply(cdrpointers(c(1,-2,3)), function(i) cdrmove(c(1,-2,3), i))
[[1]]
[1] 1 2 3

[[2]]
[1] 1 2 3

但是,假设这些有效。您可以尝试以下方法并确定它们是否使用不正确。

## Name nodes uniquely, dont be assigning to the .Globalenv like
## you are in `assn`, which wont work becuse `i` isn't being incremented.
## You could invcrement `i` in the global, but, instead,
## I would encapsulate `i` in the function's parent.frame, avoiding possible conflicts
nodeNamer <- function() {
    i <- 0
    ## Note: `i` is incremented outside of the scope of this function using `<<-`
    function(node) sprintf("v%g", (i <<- i+1))
}

## Load your functions, havent looked at these too closely,
## so just gonna assume they work
source(file="https://raw.githubusercontent.com/zediiiii/CDS/master/Generating%20Scripts.r")

cdrtree <- function(root.value) {
    root <- Node$new('root')  # assign root
    root$value <- root.value  # There seems to be a separation of value from name
    name_node <- nodeNamer()   # initialize the node counter to name the nodes

    ## Define your recursive helper function
    ## Note: you could do without this and have `cdrtree` have an additional
    ## parameter, say tree=NULL.  But, I think the separation is nice.
    have.kids <- function(node) {
        ## this function (`cdrpointers`) needs work, it should return a 0 length list, not print
        ## something and then error if there are no values
        ## (or throw and error with the message if that is what you want)
        pointers <- tryCatch({cdrpointers(node$value)}, error=function(e) return( list() ))
        if (!length(pointers)) return()
        for (pointer in pointers) {
            child_val <- cdrmove(node$value, pointer)  # does this always work?
            child <- Node$new(name_node())             # give the node a name
            child$value <- child_val
            child <- node$AddChildNode(child)
            Recall(child)                              # recurse with child
        }
    }
    have.kids(root)
    return( root )
}

library(data.tree)
res <- cdrtree(root.value=c(1,-2,3))

关于r - 在 R 中生成由节点函数递归定义的 K-Nary 树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33772031/

相关文章:

r - 如何逐行减去一个向量,保持数据帧(df)列的均值来自 df?

list - 使用 Prolog : Given a list check if the first element of the list equals the last element

用于递归搜索 FTP 特定文件名且超过 24 小时的 python 脚本

r - 根据多列用先前的值填充 NA

r - 按行比较矩阵与向量中的元素

algorithm - 两个n位数的递归除法算法

java - 统一成本搜索

javascript - 如何在 Javascript DOM 中创建树结构?

java - 将动态 Javascript 树结构加载到 JSP 中

r - Plotly:更改悬停弹出窗口样式