首先,我看到this问题,但它并没有解决我的问题。
我有一个数据结构(Trie),它包含树的每个节点的字符。
字符可以在不同的节点中重复,因此字符不是节点的id。
如果我插入{aa, abc, cash, cicero, cicelies, cigar}
,我的树将是这样的:
我的课程:
class TrieNode {
public char content;
public boolean isEnd;
public int count;
public LinkedList<TrieNode> childList;
public TrieNode(char c) {
childList = new LinkedList<TrieNode>();
isEnd = false;
content = c;
count = 0;
}
public TrieNode subNode(char c) {
if(childList != null)
for(TrieNode eachChild : childList)
if(eachChild.content == c)
return eachChild;
return null;
}
}
class Trie {
private TrieNode root;
public Trie() {
root = new TrieNode('*');
}
public void insert(String word) {
if(search(word) == true)
return;
TrieNode current = root;
for(char ch : word.toCharArray()) {
TrieNode child = current.subNode(ch);
if(child != null)
current = child;
else {
current.childList.add(new TrieNode(ch));
current = current.subNode(ch);
}
current.count++;
}
current.isEnd = true;
}
public void print() {
String fileDot = "./outputFile";
try {
FileWriter f = new FileWriter(fileDot);
BufferedWriter bf = new BufferedWriter(f);
out = new PrintWriter(bf);
createDotString();
out.close();
File g = new File(fileDot);
String arg1 = g.getAbsolutePath();
String arg2 = arg1 + ".png";
String[] c = {"dot", "-Tpng", arg1, "-o", arg2};
Process p = Runtime.getRuntime().exec(c);
p.waitFor();
}
catch(IOException ioe) {
System.out.println(ioe);
}
catch(InterruptedException iee) {
System.out.println(iee);
}
}
public void createDotString() throws IOException {
out.println("graph T {\n\trankdir = TB;");
printNodeDot(root);
out.println("}");
}
private void printNodeDot(TrieNode node) {
for(TrieNode child : node.childList) {
out.println("\t\"" + node.content + "\" -- \"" + child.content + "\";");
printNodeDot(child);
}
}
}
dot 文件是:
graph T {
rankdir = TB;
"*" -- "a";
"a" -- "a";
"a" -- "b";
"b" -- "c";
"*" -- "c";
"c" -- "a";
"a" -- "s";
"s" -- "h";
"c" -- "i";
"i" -- "c";
"c" -- "e";
"e" -- "r";
"r" -- "o";
"e" -- "l";
"l" -- "i";
"i" -- "e";
"e" -- "s";
"i" -- "g";
"g" -- "a";
"a" -- "r";
}
Graphviz生成此图片:
这只是因为“节点重复”。 我如何解决我的问题?
我以为我会为每个节点添加一个唯一标识,但我认为这是一个糟糕的解决方案,因为我不想在每个节点上添加一个字段来打印树。 还有其他解决方案吗? 另外,如何以相同级别的节点在图形中对齐的方式打印树? 我阅读使用 rankdir ,但不明白如何,至少只要我不能唯一地识别节点。
感谢。
答案 0 :(得分:0)
您为每个节点添加ID是正确的 - 我只是使用每个节点的完整路径作为其ID。对于graphviz,我还将分割节点的定义(ID和相应的标签)和边缘列表(id到id)。
结果可能是这样的:
graph T {
// nodes
"*" [label="*"];
"*a" [label="a"];
"*aa" [label="a"];
"*ab" [label="b"];
"*abc" [label="c"];
"*c" [label="c"];
...
// edges
"*" -- "*a";
"*a" -- "*aa";
"*a" -- "*ab";
"*ab" -- "*abc";
"*" -- "*c";
"*c" -- "*ca";
"*ca" -- "*cas";
"*cas" -- "*cash";
...
}
使用此代码创建此graphvizfiddle的完整结果:
var lst = new[]{"aa", "abc", "cash", "cicero", "cicelies", "cigar"};
var nodes = lst.Select(s => "*" + s).ToList()
.SelectMany(w => Enumerable.Range(1, w.Length).Select (i => w.Substring(0, i)))
.Distinct()
.ToList();
var nodedefs = nodes.Select(n => string.Format("\"{0}\" [label=\"{1}\"];", n, n.Last()));
var edges = nodes.Where(n => n.Length > 1)
.Select(n => String.Format("\"{0}\" -- \"{1}\";", n.Substring(0, n.Length-1), n));
var graph = string.Join(Environment.NewLine, nodedefs.Concat(edges));