Recursion 递归搜索树

Recursion 递归搜索树,recursion,tree,julia,Recursion,Tree,Julia,这段代码试图构建一个简单的树结构,然后搜索匹配项。有些还可以 mutable struct Tree node::String children::Vector end Tree(str::String) = Tree(str, []) Tree(a::Vector) = Tree("root", a) function Base.show(io::IO, tree::Tree, level = 0) print(io, "\t" ^ level * tree.no

这段代码试图构建一个简单的树结构,然后搜索匹配项。有些还可以

mutable struct Tree
    node::String
    children::Vector
end

Tree(str::String) =  Tree(str, [])
Tree(a::Vector) = Tree("root", a)

function Base.show(io::IO, tree::Tree, level = 0)
    print(io, "\t" ^ level * tree.node * "\n")
    for child in tree.children
        show(io, child, level + 1)
    end
end

function Base.length(t::Tree, counter = 1)
    for child in t.children
        if child != nothing
            counter += 1
            counter = length(child, counter)
        end
    end
    return counter
end

function buildtree(path)
    root = Tree(splitpath(path)[end])
    if isdir(path)
        for f in readdir(path)
            push!(root.children, buildtree(joinpath(path, f)))
        end
    end
    return root
end

function findfirstitem(t::Union{Tree, Array}, key)
    result = missing
    # if a number, return some of the children
    if isa(key, Int) || isa(key, UnitRange)
        return t.children[key]
    end
    # or look for a matching node/key
    if isa(key, String)
        for child in t.children
            if occursin(key, child.node)
                return child.node
            end
            if isa(child, Union{Tree, Array})
                findfirstitem(Tree(child.node, child.children), key)
            end
        end
    end
    return result
end

filetree = buildtree(homedir() * "/.julia/registries/General/A")
顶层查询工作正常

julia> findfirstitem(filetree, "A")

"ACME"

julia> findfirstitem(filetree, 2:4)

3-element Array{Any,1}:
ADCME
Compat.toml
Deps.toml
Package.toml
Versions.toml
---------------------------

AIBECS
Compat.toml
Deps.toml
Package.toml
Versions.toml
---------------------------

AIControl
Compat.toml
Deps.toml
Package.toml
Versions.toml
---------------------------

julia> findfirstitem(filetree, "ACME")

"ACME"
但递归并不像我想的那样展开:

julia> findfirstitem(filetree, "Compat")

missing

我的头开始被这个递归弄痛了…

这个函数不应该被赋予查看儿童的任务,因为这是由递归处理的


function findfirstitem(t::Union{Tree, Array}, key)
    # if a number, return some of the children
    if key isa Int || key isa UnitRange
        return t.children[key]
    end
    # or look for a matching node/key
    if key isa String
        if occursin(key,t.node)
            return t
        else
            for child in t.children
                found = findfirstitem(child, key)
                if !ismissing(found)
                    return found
                end
            end
        end
    end
    return missing
end

但这取决于您对搜索算法的期望。它应该先搜索深度还是广度?

该函数不应该被赋予查看子对象的任务,因为这是由递归处理的


function findfirstitem(t::Union{Tree, Array}, key)
    # if a number, return some of the children
    if key isa Int || key isa UnitRange
        return t.children[key]
    end
    # or look for a matching node/key
    if key isa String
        if occursin(key,t.node)
            return t
        else
            for child in t.children
                found = findfirstitem(child, key)
                if !ismissing(found)
                    return found
                end
            end
        end
    end
    return missing
end
但这取决于您对搜索算法的期望。它应该先搜索深度还是广度?

在我看来,如果child是数组,findfirstitemTreechild.node、child.children、key将失败?顺便说一句,为什么不为该部分使用dispatch?我也试图将children字段设置为::Tree,但这些递归类型定义很难,因此使用联合。在我看来,如果child是数组,findfirstitemTreechild.node、child.children、key将失败?顺便说一句,为什么不为该部分使用dispatch呢?我试图使children字段也成为::Tree,但是这些递归类型定义很难,因此使用union。