I'm currently working through "Algorithms in java" by Robert Sedgewick (3rd edition, german version) on my own and am trying to solve one of the exercises there, currently one from the "creative-solutions"-section.
As part of the solution of one exercise I'm trying to sort an unsorted tree by the amount of children each Node has, nodes with larger amounts of children coming first:
- Sort all child-nodes of a parent n0 according to the amount of child-nodes
nNodes
that the child-nodes themselves have, sort from left to right from largest to lowest. Perform this sorting for all Nodes in the tree. - If 2 sibling-nodes n1 and n2 of these child-nodes have identical
nNodes
, go to the child-nodes of n1 and n2 try to sort these two according to thenNodes
of their largest children. If no difference is found, try to sort according to thenNodes
of their 2nd largest children, etc. - If you run out of children, go to the child-node of the child in 2 with the largest amount of children and repeat 2. etc. etc.
- If after all comparisons it turns out that both n1 and n2 are roots of trees with identical shape, it doesn't matter which of the two comes first.
To give a visual comparison, this "rule" would result in the following tree sorting as depicted here: Example of Sorting.
The code
The problem I'm stuck at is correctly implementing the sorting. Each tree is composed of nodes. Each Node contains a value (so that you have a "name" for the node, not important for the sorting itself which only cares about the amount of children each node has) and an arrayList of Node-references to the child-nodes of that node. For nodes without children that ArrayList has size 0. The key here is sorting the ArrayLists in all of the Nodes, which I'm currently trying to do using the built-in sort method with a Comparator object. I think I have to approach this recursively, which makes the whole thing really messy because I'm currently having a comparator method calling itself while also calling "sort" for other ArraLists in the same method. The sortForest
method below gives me stack-overflow errors when I'm trying it out in some main-methods to test it.
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;
}
Question
How can one get this code to work? I'm somewhat sure this is roughly in the ballpark of a correct solution, but I've tried to think this through over several hours now and can't figure out one. I'm convinced that this is giving me stack-overflows due to a never-ending recursion being in there somewhere, I just don't see it. The recursion in general is giving me problems to properly do this mentally. I couldn't find identical questions to this and those that were similar concerned themselves with binary trees instead of unordered ones.