Finden Sie alle Teilbäume in einem Baum, die mit einem bestimmten Teilbaum in Java
Schreibe ich code in Java verwendet eine ungeordnete, verwurzelter Baum, wo jeder Knoten kann eine beliebige Anzahl von Kind-Knoten. Gegeben ein Baum T und ein Teilbaum S, ich möchte in der Lage sein, um herauszufinden, alle Teilbäume in T, match S (das ist alles, die Teilbäume in T sind isomorph zu S).
Einen Teilbaum von T ist isomorph zu S, wenn die Knoten von S zugeordnet sein kann, die Knoten von T so, dass die Kanten von S-Karte, um die Kanten in T.
Einen Vorherige Frage wurde gefragt, wie Sie zu finden, wenn ein Baum enthält eine weitere Unterstruktur aber ich möchte in der Lage zu finden ALLE Teilbäume in T entsprechen S. außerdem will ich in der Lage sein, aus der die Zuordnung jeder Knoten in jedem match in T, um die entsprechenden Knoten in S.
Ist, wenn eine übereinstimmung gefunden wird, sollte es zurückgegeben werden und nicht einfach ein Zeiger auf den Knoten in T, wo ein Baum verwurzelt ist, entspricht S, aber das match sollte zurückgegeben werden, wie so etwas wie eine Liste von Paaren von Zeigern auf Knoten [(T1,S1),(T2,S2),...(Tn,Sn)], so dass T1 ist ein Zeiger auf einen Knoten in T, die Karten auf Knoten S1 im Teilbaum und so weiter.
Alternativ einfach eine Liste von Paaren von Werten zurückgegeben werden, da jeder Knoten im Baum T und Teilbaum von S hat eine eindeutige integer-id zugeordnet.
Beispiel:
Gegebenen Baum T wie folgt:
a
/ \
b c
/ \
d e
und Teilbaum S:
x
/ \
y z
folgenden die Liste der Spiele, die zurückgegeben werden sollen:
[(a,x),(b,y),(c,z)]
[(b,x),(d,y),(e,z)]
Einem einzigartigen match wird bestimmt durch die Menge der Knoten in T, nicht das mapping zwischen den Knoten in T und S.
Also das folgende match:
[(a,x),(b,z),(c,y)]
als Duplikat
[(a,x),(b,y),(c,z)]
da Sie die gleiche Menge von Knoten aus T (a,b,c), so dass nur eines der Spiele, die zurückgegeben werden sollen.
Als ein weiteres Beispiel, da der Baum T:
a
/|\
b c d
und Teilbaum S:
x
/ \
y z
folgenden die Liste der Spiele, die zurückgegeben werden sollen:
[(a,x),(b,y),(c,z)]
[(a,x),(b,y),(d,z)]
[(a,x),(c,y),(d,z)]
Kann jemand geben Sie ein beliebiges Beispiel-code, wie dies zu tun?
Bearbeiten (in Bezug auf Chris Kannon ' s Kommentar):
Ich denke, Sie möchten, dass jemand den code
die Antwort für Sie? Wie weit haben Sie
bekommen? Welchen code hast du geschrieben? –
Chris Kannon vor 1 Stunde
Ich habe den folgenden code, die, wenn Sie ausgeführt wird, erzeugt eine Liste (matchesList) von Zeigern auf Knoten in dem Baum, in dem Teilbaum verwurzelt sind, dass entsprechend der gegebenen Teilstruktur. Allerdings kann es mehrere Teilbäume verwurzelt in der gleichen Knoten-und derzeit jeder Knoten wird nur dann Hinzugefügt werden, höchstens einmal zu matchesList unabhängig davon, wie viele Spiele sind dort verwurzelt.
Zudem kann ich nicht arbeiten heraus, wie man die Zuordnung oben beschrieben zwischen den Knoten im Teilbaum und Knoten in das match gefunden in den ursprünglichen Baum.
package Example;
import java.util.LinkedList;
import java.util.Vector;
public class PartialTreeMatch {
public static void main(String[] args) {
NodeX testTree = createTestTree();
NodeX searchTree = createSearchTree();
System.out.println(testTree);
System.out.println(searchTree);
partialMatch(testTree, searchTree);
}
static LinkedList<NodeX> matchesList = new LinkedList<NodeX>();
private static boolean partialMatch(NodeX tree, NodeX searchTree) {
findSubTreeInTree(tree, searchTree);
System.out.println(matchesList.size());
for (NodeX n : matchesList) {
if (n != null) {
System.out.println("Found: " + n);
}
}
return false;
}
private static NodeX findSubTreeInTree(NodeX tree, NodeX node) {
if (tree.value == node.value) {
if (matchChildren(tree, node)) {
matchesList.add(tree);
}
}
NodeX result = null;
for (NodeX child : tree.children) {
result = findSubTreeInTree(child, node);
if (result != null) {
if (matchChildren(tree, result)) {
matchesList.add(result);
}
}
}
return result;
}
private static boolean matchChildren(NodeX tree, NodeX searchTree) {
if (tree.value != searchTree.value) {
return false;
}
if (tree.children.size() < searchTree.children.size()) {
return false;
}
boolean result = true;
int treeChildrenIndex = 0;
for (int searchChildrenIndex = 0; searchChildrenIndex < searchTree.children
.size(); searchChildrenIndex++) {
//Skip non-matching children in the tree.
while (treeChildrenIndex < tree.children.size()
&& !(result = matchChildren(tree.children
.get(treeChildrenIndex), searchTree.children
.get(searchChildrenIndex)))) {
treeChildrenIndex++;
}
if (!result) {
return result;
}
}
return result;
}
private static NodeX createTestTree() {
NodeX subTree2 = new NodeX('A');
subTree2.children.add(new NodeX('A'));
subTree2.children.add(new NodeX('A'));
NodeX subTree = new NodeX('A');
subTree.children.add(new NodeX('A'));
subTree.children.add(new NodeX('A'));
subTree.children.add(subTree2);
return subTree;
}
private static NodeX createSearchTree() {
NodeX root = new NodeX('A');
root.children.add(new NodeX('A'));
root.children.add(new NodeX('A'));
return root;
}
}
class NodeX {
char value;
Vector<NodeX> children;
public NodeX(char val) {
value = val;
children = new Vector<NodeX>();
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append('(');
sb.append(value);
for (NodeX child : children) {
sb.append(' ');
sb.append(child.toString());
}
sb.append(')');
return sb.toString();
}
}
Den code oben versucht zu finden, die alle Teilgraphen in:
A
/|\
A A A
/ \
A A
dem match:
A
/ \
A A
Den code erfolgreich erkannt wird, dass es eine übereinstimmung wurzelt eine der top-Knoten im ersten Baum, und das 3. Kind der erste Baum. Allerdings gibt es tatsächlich 3 Spiele verwurzelt in der top-Knoten, nicht nur eine. Darüber hinaus wird der code nicht aufbauen, ein mapping zwischen den Knoten in der Baumstruktur und Knoten in dem Teilbaum, und ich kann nicht herausfinden, wie dies zu tun.
Kann mir jemand einen Rat, wie dies zu tun?
- Ich denke, Sie möchten, dass jemand den code der Antwort für Sie? Wie weit haben Sie bekommen? Welchen code hast du geschrieben?
- +1 für eine tolle Erklärung.. naja, eigentlich alle Stimmen für heute, aber der Wille zählt
- @Chris Kannon : ich habe aktualisiert die Frage, in Antwort auf Ihren Kommentar und code geschrieben, so weit.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich denke, deine rekursive Methode braucht, um eine Liste der partial-matches, statt nur einen booleschen Wert. Das würde gehen einen langen Weg, um beide zu lösen Ihre Probleme (das Bedürfnis, wieder die Liste der matches, sowie das finden mehrere Spiele).
Java-ähnlichen pseudocode für die rekursive Funktion könnte wie folgt Aussehen:
Beachten Sie, dass diese Funktion nicht testen treeNode.Wert == searchNode.Wert, oder fügen Sie diese der Liste. Der Anrufer muss, das zu tun. Diese Funktion muss ausgeführt werden bei jedem Knoten des Baumes.
Wie Sie derzeit gestaltet ist, ist es wahrscheinlich zu viel Speicher verwendet, könnte aber optimiert werden.
Diese hilfreich sein kann.