【发布时间】:2017-09-11 21:29:24
【问题描述】:
我目前正在自己研究 Robert Sedgewick 的“Java 算法”(第 3 版,德语版),并试图解决其中的一个练习,目前是“创意解决方案”部分的一个练习。
作为一个练习的解决方案的一部分,我尝试按每个节点拥有的子节点数量对未排序的树进行排序,具有大量子节点的节点首先出现:
- 根据子节点本身拥有的子节点
nNodes的数量对父n0 的所有子节点进行排序,从左到右从大到小排序。对树中的所有节点执行此排序。 - 如果这些子节点中的 2 个兄弟节点 n1 和 n2 具有相同的
nNodes,则转到 n1 和 n2 的子节点尝试根据它们最大子节点的nNodes对这两个节点进行排序。如果没有发现差异,尝试按照他们的第二大孩子的nNodes等排序。 - 如果你的孩子用完了,去 2 中孩子数量最多的孩子的孩子节点,重复 2. etc. etc.
- 如果经过所有比较后发现 n1 和 n2 都是形状相同的树的根,那么两者中的哪一个先出现并不重要。
为了进行直观比较,此“规则”将导致如下所示的树排序:Example of Sorting。
代码
我遇到的问题是正确实现排序。每棵树都由节点组成。每个节点都包含一个值(这样您就有一个节点的“名称”,对于排序本身并不重要,它只关心每个节点具有的子节点数量)和一个节点引用的数组列表,该节点引用的子节点节点。对于没有子节点的节点,ArrayList 的大小为 0。这里的关键是对所有节点中的 ArrayLists 进行排序,我目前正在尝试使用带有 Comparator 对象的内置排序方法进行排序。我认为我必须递归地处理这个问题,这使得整个事情变得非常混乱,因为我目前有一个比较器方法调用自身,同时还在同一方法中为其他 ArraLists 调用“排序”。下面的sortForest 方法在我用一些主要方法进行测试时给了我堆栈溢出错误。
static NodeComparator comp = new NodeComparator();
static class Node {
int value;
ArrayList<Node> children;
Node(int value, ArrayList<Node> children) {
this.value = value;
this.children = children;
}
}
static class NodeComparator implements Comparator<Node> {
public NodeComparator() {
}
public int compare(Node n1, Node n2) {
/*-
* Base Case 1: Both Nodes are leafs (isEmpty() is true) - they are
* equal -> return 0.
* Base Case 2/3: One of the Nodes is a leaf while the other isn't -
* the one that is a leaf is "lower" than the one that isn't. ->
* return (-) 1.
*/
if (n1.children.isEmpty() && n2.children.isEmpty()) {
return 0;
} else if (n2.children.isEmpty()) {
n1.children.sort(comp);
return 1;
} else if (n1.children.isEmpty()) {
n2.children.sort(comp);
return -1;
} else {
/* Get the amount of children the 2 nodes n1 and n2 have */
int nChildren1 = (n1.children.isEmpty()) ? 0 : n1.children.size();
int nChildren2 = (n2.children.isEmpty()) ? 0 : n2.children.size();
/* Always sort the ArrayList of children that they have */
n1.children.sort(comp);
n2.children.sort(comp);
/*
* If n1 and n2 have equal amounts of children, compare the
* amounts of children their children have, from largest to
* lowest
*/
if (nChildren1 == nChildren2) {
int result = 0;
for (int i = 0; (i < nChildren1) && (result == 0); i++) {
compare(n1.children.get(i), n2.children.get(i));
}
return result;
} else {
/*- If one node has more children than the other, sort accordingly */
return ((nChildren1 > nChildren2) ? 1 : -1);
}
}
}
}
static void sortForest(Node root) {
for (int i = 0; i < root.children.size(); i++) {
sortForest(root.children.get(i));
root.children.sort(comp);
}
return;
}
问题
如何让这段代码工作?我有点确定这大致处于正确解决方案的范围内,但是我已经尝试了几个小时来思考这个问题,但无法弄清楚。我确信这给了我堆栈溢出,因为那里有一个永无止境的递归,我只是看不到它。一般来说,递归给我带来了在心理上正确执行此操作的问题。我找不到与此相同的问题,而那些相似的问题则关注二叉树而不是无序树。
【问题讨论】:
标签: java sorting tree stack-overflow