首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在围棋中从孩子身上走过一个谱系

在围棋中从孩子身上走过一个谱系
EN

Stack Overflow用户
提问于 2020-02-28 14:39:23
回答 1查看 48关注 0票数 0

我有一个大的群体谱系(map[int][]int),其中关键是动物,而父母(两个)在价值切片。没有父母的动物会对父母有负整数。

其次,我有一个动物列表,我想要建立他们的特定的血统,并写入一个文件。我名单上所有的动物血统都应该写在同一个档案里。

代码语言:javascript
复制
pedigree := map[int][]int{
    1:  []int{2, 3},
    2:  []int{-1, 5},
    3:  []int{6, 7},
    4:  []int{8, 9},
    5:  []int{-1, -2},
    6:  []int{8, -2},
    7:  []int{-1, -2},
    8:  []int{-1, -2},
    9:  []int{10, -2},
    10: []int{-1, 4}
}

list := []int{1, 4}

以及我对io.Writer编写的文件的期望:

代码语言:javascript
复制
  1   2   3
  2  -1   5
  3   6   7
  5  -1  -2
  6   8  -2
  7  -1  -2
  8  -1  -2
  4   8   9
  9  10  -2
 10  -1   4

所以我需要一个递归函数来遍历这个谱系,从基本的动物开始,然后在所有的路径上继续,直到有负数的父母到达。

,更重要的是,,在我的名单中,动物被认为是引起系谱循环的动物(动物4成为自己的伟大父母)。

我尝试了以下代码:

代码语言:javascript
复制
type tree struct {
    sire   *tree
    dam    *tree
    animal int
    base   int
    path   []int
}

func newTree(a, s, d, b int) tree {
    return tree{
        animal: a,
        sire:   &tree{animal: s, base: b},
        dam:    &tree{animal: d, base: b},
        base:   b,
    }
}

for _, animal := range list {
    myTree = newTree(animal, pedigree[animal][0], pedigree[animal][1], 0)
    walk(myTree, written, fw) // written is a map of integers and fw is io.Writer
}

func walk(t tree, written map[int]int, writer io.Writer) tree {
    style := "%12d%12d%12d\n"
    if t.animal == t.base {
        return t
    }
    if t.base == 0 {  // for the first iteration
        t.base = t.animal
    }
    if _, ok := written[t.animal]; !ok {
        sire := t.sire.animal
        dam := t.dam.animal
        if sire == 0 {
            sire = t.base
        }
        if dam == 0 {
            dam = t.base
        }
        written[t.animal] = 0
        io.WriteString(writer, fmt.Sprintf(style, t.animal, sire, dam))
    }
    // Shift forward.
    if t.sire.animal > 0 {
        myTree := newTree(t.sire.animal, pedigree[t.sire.animal][0], pedigree[t.dam.animal][1], t.base)
        walk(myTree, written, writer)
    }
    if t.dam.animal > 0 {
        myTree := newTree(t.dam.animal, pedigree[t.dam.animal][0], pedigree[t.dam.animal][1], t.base)
        walk(myTree, written, writer)
    }
    return t
}

我的谱系大约有1300万只动物,但我不能让这个函数停在正确的位置,在几只动物做完后引起stack overflow恐慌。我相信我的一些问题是:

参与循环的动物是基础动物,所以我应该检查参与循环的(1->2->3->1)

  • An动物是,而不是,基础动物(1->2->3->4->5->6->3)

任何帮助都将不胜感激。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-02-28 14:54:43

因为你可以在你的谱系图中有循环,你可能会陷入这样的循环。这意味着你必须检测循环并停止在那里建立。你可以通过稍微改变你的树来做到这一点。

首先,通过值传递tree对象,但将指针附加到它。将指针传递给周围的树:

代码语言:javascript
复制
func walk(t *tree, written map[int]int, writer io.Writer) *tree {
}

更好的办法可能是:

代码语言:javascript
复制
func (t *tree) walk(written map[int]int, writer io.Writer) {...}

还应该向树中添加一个*parent,以便检测循环:

代码语言:javascript
复制
type tree struct {
    parent *tree
    sire   *tree
    dam    *tree
    animal int
    base   int
    path   []int
}

每次创建新级别时,都要适当地设置父级:

代码语言:javascript
复制
myTree := newTree(t.sire.animal, pedigree[t.sire.animal][0], pedigree[t.dam.animal][1], t.base)
myTree.parent=t
myTree.walk(written, writer)

然后添加一个函数来测试您是否要进入一个循环:

代码语言:javascript
复制
func (t *tree) loop(animal int) bool {
   for t!=nil {
       if t.animal==animal {
          return true
       }
       t=t.parent
   }
   return false
}

检查你是否进入了一个循环:

代码语言:javascript
复制
if !myTree.loop(myTree.animal) {
   myTree.walk(written, writer)
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60453927

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档