2012-04-01 38 views
0

这个问题通常与语言无关(尽管如此,我正在使用Java/Processing)。我需要使用一些数据库输出来绘制一个树形图。规则很简单:绘制树形图 - 如何组织存储阵列?

图只有一个Root。 每个节点可以有几个孩子,但只有一个父母。

我在绕过如何将数据提供给绘图函数时遇到了麻烦。我从获取数据的数据库(它的Rails/MySQL的)具有以下结构(我使用伪代码,以避免不必要的自我指涉的has_many:通过细节):

Graph 
has_many :nodes 

Node 
has_many :siblings 
has_one :parent 
has_many :children 

的问题是 - 我应该如何组织阵列我将节点信息放入以及如何循环访问数组?算法的伪代码将会很棒。

如果您发现某些信息缺少答案,请告诉我,我很乐意扩大问题/添加数据。

P.S.我并不是在寻找可以为我绘制图形的框架/服务的建议,实际上我需要使用我现有的工具来完成这些工作。

谢谢!

编辑:

这就是我现在怎么绘制图形...它源自like [“0root”,“2child”,2child2' ,‘4child_child’]数组需要一个字一个和重建树假设如果数组的下一个元素的(int)前缀大于2,那么它是一个孩子,如果它小于2,那么它是一个级别(父级的兄弟)。相对于兄弟姐妹的位置是根据数组中具有相同前缀的元素的总数来计算的。我想知道是否有更优雅的方式来做到这一点..?

图(){ wordList = new ArrayList(); nodeList = new ArrayList(); sibList = new ArrayList(); }

Integer sibNumber(int idx<char>) { 
    Map<Integer, Integer> sibCount = new HashMap<Integer, Integer>(); 
    for (Integer sibling: sibList) { 
     Integer count = sibCount.get(sibling); 
     sibCount.put(sibling, (count==null) ? 1 : count+1); 
    } 
    Integer result = sibCount.get(idx); 
    return result; 
    } 


    void update(String wrd) { 
    wordList.add(wrd); 

    String word = wrd; 
    String[][] m = matchAll(wrd, "(\\d*)"); 
    int index = (int) m[0][0]; 
    char number = (char) index; 
    sibList.add(index); 
// println(wrd); 
    word = word.replaceAll(number,""); 
    Integer siblingsNum = sibNumber(index); 
    if (sibList.size()>=2) { 
     lastIndex = sibList.get(sibList.size()-2); 
     int indexDiff = index-lastIndex; 
     if (indexDiff != 0) { 
     for (int i=sibList.size()-1; i>0; i--) { 
      if (index-sibList.get(i) == 2) { 
      parNode = nodeList.get(i); 
      break; 
      } 
     } 
     } 
    } 
    if (index == 2) { 
     parNode = nodeList.get(0); 
    } 

    node = new Node(word, index, siblingsNum, parNode); 
    nodeList.add(node); 

    } 

    void clean() { 
    nodeList = new ArrayList<Node>(); 
    sibList = new ArrayList<Integer>(); 
    } 


    void display() { 
    for (int i = 0; i < nodeList.size(); i++) { 
     nd = nodeList.get(i); 

     if (nd.parent != null) { 

     stroke(255, 0, 0); 
     VerletSpring2D spring=new VerletSpring2D(nd.origin,nd.parent.origin,80,0.01); 
     physics.addParticle(nd.origin); 
     physics.addSpring(spring); 
     line(nd.origin.x+nd.w/2, nd.origin.y, nd.parent.origin.x+nd.w/2, nd.parent.origin.y+nd.parent.h); 
     } 
     nd.display(); 
    } 
    } 
} 
+0

而不是使用数组,为什么你不能有一个名为“节点”,可以适合目的的类? – 2012-04-01 17:13:46

回答

0

您是否必须使用数组?这个问题的自然解决方案是实现一个'Node'类,它有子节点的引用。这适用于递归算法,这将允许您(例如)找到特定的节点。 然后您需要首先引用根节点。

public class Node { 
    private Node parent; 
    private List<Node> children; 

    public Node findNode(String nodeName) { 
    // Is it this node? 
    // Iterate through all child nodes, calling findNode on each 
    } 
} 
+0

我必须将Rails模型中的数据传递给用Java/Processing编写的实际graph_draw()函数,所以我必须以某种方式告知graph_draw()它正在接收哪种节点(它是否有孩子?它是否有兄弟姐妹?)..我想我无法确定哪些参数应该与实际的Node.content一起传递。 – Stpn 2012-04-01 18:13:41

+0

graph_draw()期望的参数是什么?这是你正在使用的第三方库吗?有没有API的文档? – 2012-04-01 18:20:33

+0

graph_draw()只是一个函数,我在处理,它可以采取任何参数..我会更新与更多关于该功能的信息的问题: – Stpn 2012-04-01 18:24:12