【问题标题】:Drawing a tree-like graph - how to organize the storage array?绘制树状图——如何组织存储阵列?
【发布时间】:2012-04-01 16:51:49
【问题描述】:

这个问题通常与语言无关(尽管如果这很重要,我使用的是 Java/Processing)。我需要使用一些数据库输出绘制一个树状图。规则很简单:

图只有一个根。 每个节点可以有多个子节点,但只有一个父节点。

我在思考如何将数据提供给绘图函数时遇到了麻烦。我从中获取数据的数据库(它是 Rails/MySQL)具有以下结构(我使用伪代码来避免不必要的自引用 has_many :通过详细信息):

Graph
 has_many :nodes

Node
 has_many :siblings
 has_one :parent
 has_many :children

问题是 - 我应该如何组织我将节点信息放入的数组以及如何遍历该数组?算法的伪代码将是惊人的。

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

附:我并不是真的在寻找一些可以为我绘制图表的框架/服务的建议,我实际上需要使用我当前的工具来做到这一点。

谢谢!

编辑:

这就是我现在绘制图形的方式...它从像 ['0root', '2child', 2child2', '4child_child'] 这样的数组中一个接一个地获取单词,并假设 if (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();
    }
  }
}

【问题讨论】:

  • 不使用数组,为什么不能有一个适合目的的名为“Node”的类?

标签: java graph tree pseudocode graph-algorithm


【解决方案1】:

你必须使用数组吗?这个问题的自然解决方案是实现一个“节点”类,它具有对子节点的引用。这适用于递归算法,该算法将允许您(例如)找到特定的节点。 然后,您需要开始的只是对根节点的引用。

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
  }
}

【讨论】:

  • 我必须将数据从 Rails 模型传递到实际的 graph_draw() 函数,该函数是用 Java/Processing 编写的,所以我必须以某种方式通知 graph_draw() 它正在接收什么样的节点(是吗?有孩子吗?它有兄弟姐妹吗?)..我想我很难确定应该与实际 Node.content 一起传递哪些参数..
  • graph_draw() 期望什么参数?这是您正在使用的第三方库吗? API 是否有任何文档?
  • graph_draw() 只是我在处理中的一个函数,它可以采用任何参数。我将使用有关该函数的更多信息更新问题:
猜你喜欢
  • 1970-01-01
  • 2020-10-17
  • 2015-05-21
  • 2012-06-25
  • 1970-01-01
  • 1970-01-01
  • 2020-05-20
  • 2020-06-06
  • 2020-02-07
相关资源
最近更新 更多