使用golang从一张桌子做一棵树?

时间:2014-04-09 09:02:25

标签: tree go treenode

我想从桌子上做一棵树。 表格如下:

OrgID   OrgName        parentID
A001    Dept           0 -----th top
A002    subDept1        A001
A003    sub_subDept    A002
A006    gran_subDept   A003
A004    subDept2        A001 

我希望结果如下,如何使用go:

Dept

--subDept1

----sub_subDept

------gran_subDept

--subDept2

2 个答案:

答案 0 :(得分:5)

如果要将行解析为树结构,可以这样做:

package main

import (
    "bufio"
    "fmt"
    "io"
    "os"
    "strings"
)

type Node struct {
    name     string
    children []*Node
}

var (
    nodeTable = map[string]*Node{}
    root      *Node
)

func add(id, name, parentId string) {
    fmt.Printf("add: id=%v name=%v parentId=%v\n", id, name, parentId)

    node := &Node{name: name, children: []*Node{}}

    if parentId == "0" {
        root = node
    } else {

        parent, ok := nodeTable[parentId]
        if !ok {
            fmt.Printf("add: parentId=%v: not found\n", parentId)
            return
        }

        parent.children = append(parent.children, node)
    }

    nodeTable[id] = node
}

func scan() {
    input := os.Stdin
    reader := bufio.NewReader(input)
    lineCount := 0
    for {
        lineCount++
        line, err := reader.ReadString('\n')
        if err == io.EOF {
            break
        }
        if err != nil {
            fmt.Printf("error reading lines: %v\n", err)
            return
        }
        tokens := strings.Fields(line)
        if t := len(tokens); t != 3 {
            fmt.Printf("bad input line %v: tokens=%d [%v]\n", lineCount, t, line)
            continue
        }
        add(tokens[0], tokens[1], tokens[2])
    }
}

func showNode(node *Node, prefix string) {
    if prefix == "" {
        fmt.Printf("%v\n\n", node.name)
    } else {
        fmt.Printf("%v %v\n\n", prefix, node.name)
    }
    for _, n := range node.children {
        showNode(n, prefix+"--")
    }
}

func show() {
    if root == nil {
        fmt.Printf("show: root node not found\n")
        return
    }
    fmt.Printf("RESULT:\n")
    showNode(root, "")
}

func main() {
    fmt.Printf("main: reading input from stdin\n")
    scan()
    fmt.Printf("main: reading input from stdin -- done\n")
    show()
    fmt.Printf("main: end\n")
}

答案 1 :(得分:4)

根据您的问题和评论中提供的信息,可以解决您的问题的是普通的递归循环。

package main

import "fmt"

type Org struct {
    OrgID    string
    OrgName  string
    parentID string
}

func printTree(tbl []Org, parent string, depth int) {
    for _, r := range tbl {
        if r.parentID == parent {
            for i := 0; i < depth; i++ {
                fmt.Print("--")
            }
            fmt.Print(r.OrgName, "\n\n")
            printTree(tbl, r.OrgID, depth+1)
        }
    }
}

func main() {
    data := []Org{
        {"A001", "Dept", "0 -----th top"},
        {"A002", "subDept1", "A001"},
        {"A003", "sub_subDept", "A002"},
        {"A006", "gran_subDept", "A003"},
        {"A004", "subDept2", "A001"},
    }

    printTree(data, "0 -----th top", 0)
}

<强>结果:

Dept

--subDept1

----sub_subDept

------gran_subDept

--subDept2

游乐场: http://play.golang.org/p/27CQAhI8gf

请注意,如果父项是其子项的后代,则此递归函数可能会陷入循环中。