我试图压缩给定节点的所有祖先,让它们指向传递给
的参数节点的根目录。 private E compressToRoot (E e) throws IllegalArgumentException;
例如,在上图中,如果我执行了compressToRoot(D),则D将直接指向A,而C将直接指向A.如果参数和根之间存在其他节点,则它们都将指向甲
所有标签和箭头都存储在两个单独的地图中:
private Map<E,E> parentMap = new HashMap<E,E>(); //labels + arrows
我可以通过(1)保持D和根之间的所有节点来完成这个方法。 (2)将设置的所有元素指向(make parent)根(3)返回根。
然而,我仍然坚持如何遍历此地图以获取根。因此,对于方法,我会按照
的方式做一些事情private E compressToRoot (E e) throws IllegalArgumentException {
Set<E> collectLables = new HashSet<E>();
E root = null;
//get root.
for (E cycle : parentMap.keys()) {
while (parentMap.get(e) != e)
e = parentMap.get(e);
if (parentMap.get(e) == e)
root = cycle;
}
//collect all labels from parameter to root.
for (E element : parentMap.keys()) {
while (parentMap.get(e) != root) {
collectLables.add(element);
}
}
}
但是我不确定如何循环通过给定节点的父节点到根节点。
答案 0 :(得分:1)
我一直坚持如何遍历这张地图以找到根。
看来你对“root”的定义是指向自身的唯一节点。它不是特别有效,但你可以只寻找一个这样的元素:
E findRoot(Map<E, E> parentMap) {
for (Map.Entry<E, E> entry: parentMap.entrySet() {
if (entry.key().equals(entry.value()) {
return entry;
}
}
// parentMap is empty, or the graph is corrupted
// handle this edge case however you want
return null;
}
答案 1 :(得分:1)
递归很漂亮,但如果到根的最长路径的长度可能变大,则支持迭代方法。你不想用完堆栈。
private E compressToRoot(E node) {
if (parentMap.get(node) != node)
parentMap.set(node, compressToRoot(node));
return parentMap.get(node);
}
private E compressToRoot(E cursor) {
E node;
ArrayList<E> nodes = new ArrayList<E>();
while ((node = parentMap.get(cursor)) != cursor) {
nodes.add(cursor);
cursor = node;
}
for (node : nodes)
parentMap.set(node, cursor);
return cursor;
}
答案 2 :(得分:1)
rambo coder's answer above略有改善,取决于地图的效率。只需遍历路径两次,就可以在不使用ArrayList
的额外内存和开销的情况下完成此操作:
private E compressToRoot(E cursor) {
E cursor2 = cursor;
E node = parentMap.get(cursor);
while (node != cursor) {
cursor = node;
node = parentMap.get(node);
}
// Now cursor (and node) are the root.
node = parentMap.get(cursor2);
while (node != cursor2) {
parentMap.set(cursor2, cursor);
cursor2 = node;
node = parentMap.get(node);
}
return cursor;
}