Le moyen le plus efficace de tester les deux arbres binaires pour l'égalité
Comment voulez-vous mettre en œuvre en Java de l'arbre binaire classe de nœud et l'arbre binaire de la classe de soutien le plus efficace (à partir du moment de l'exécution du point de vue de l'égalité méthode de contrôle (aussi doit être mise en œuvre):
boolean equal(Node<T> root1, Node<T> root2) {}
ou
boolean equal(Tree t1, Tree t2) {}
Tout d'abord, j'ai créé la classe de Nœud comme suit:
public class Node<T> {
private Node<T> left;
private Node<T> right;
private T data;
//standard getters and setters
}
et puis la méthode equals qui prend 2 nœuds racine comme un des arguments et exécute le standard de comparaison récursive:
public boolean equals(Node<T> root1, Node<T> root2) {
boolean rootEqual = false;
boolean lEqual = false;
boolean rEqual = false;
if (root1 != null && root2 != null) {
rootEqual = root1.getData().equals(root2.getData());
if (root1.getLeft()!=null && root2.getLeft() != null) {
//compare the left
lEqual = equals(root1.getLeft(), root2.getLeft());
}
else if (root1.getLeft() == null && root2.getLeft() == null) {
lEqual = true;
}
if (root1.getRight() != null && root2.getRight() != null) {
//compare the right
rEqual = equals(root1.getRight(), root2.getRight());
}
else if (root1.getRight() == null && root2.getRight() == null) {
rEqual = true;
}
return (rootEqual && lEqual && rEqual);
}
return false;
}
Ma deuxième tentative a été de mettre en œuvre les arbres à l'aide de tableaux et index pour la traversée. Ensuite, la comparaison pourrait être faite en utilisant les opérations bit à bit (ET) sur les deux tableaux - lire le bloc de 2 tableaux et masque de l'un par l'autre à l'aide ET logique. Je n'ai pas réussi à obtenir mon code de travail donc je n'ai pas poster ici (je vous remercie de votre mise en œuvre de la deuxième idée ainsi que vos améliorations).
Pensées, la façon de faire de test d'égalité pour les arbres binaires le plus efficacement?
MODIFIER
La question suppose l'égalité structurelle. (Pas la sémantique de l'égalité)
Cependant, le code qui teste la sémantique de l'égalité par exemple, "Devrions-nous considérer les deux arbres à être égaux si leur contenu est identique, même si leur structure n'est pas?" Serait juste de parcourir l'arbre dans l'ordre et il devrait être très simple.
- "Doit-on l'envisager..." suggère un avis subjectif, et en faisant en SORTE de ne pas l'idéal pour ces questions [pourrait être fermé comme "non constructif"]. Vous devez définir, elle est: l'égalité structurelle ou semantical l'égalité, vous êtes après. [au moins de l'OMI]
Vous devez vous connecter pour publier un commentaire.
Bien pour une chose que vous êtes toujours vérifier les branches, même si vous l'apercevez que les racines sont inégales. Votre code sera plus simple (OMI) et plus efficace si vous venez de rentrer
false
dès que vous avez repéré une inégalité.Une autre option pour simplifier les choses, c'est pour permettre à votre
equals
méthode d'accepternull
valeurs et de comparer les deux valeurs null comme étant égales par ailleurs. De cette façon, vous pouvez éviter tous ces nullité des contrôles dans les différentes branches. Ce ne sera pas le rendre plus efficace, mais ça va être plus simple:Il faut noter que ceci ne fonctionnera pas si
root1.getData()
retournenull
. (Qui peut ou peut ne pas être possible avec la façon dont vous êtes l'ajout de nœuds.)EDIT: Comme discuté dans les commentaires, vous pouvez utiliser des codes de hachage pour faire un très rapide "début" - mais il serait ajouter de la complexité.
Soit vous avez besoin pour faire vos arbres immuable (ce qui est une autre discussion) ou vous avez besoin chaque nœud de connaître ses parents, de sorte que lorsque le nœud est modifiée (par exemple, par l'ajout d'une feuille ou de la modification de la valeur), il doit mettre à jour son code de hachage et de demander à ses parents de mettre à jour trop.
hashcode
avant d'utiliserequals
. Vous êtes toujours face à un O(n) le temps d'exécution.hashCode()
aider? Il aurait pour effectuer une itération sur l'arbre, ce qui serait un O(n) opérations... et même alors, vous feriez toujours à itérer sur tout, si les deux codes de hachage sont égaux.hashCode
mise en œuvre n'est-ce pas? 1. vous pouvez l'utiliser pour l'objet de données à seulement 2. si vous aussi vous voulez de les utiliser pour les nœuds que vous pouvez utiliser un différentiel de hachage qui est mis à jour uniquement lorsque les nœuds changements qui conduiront à un O(1) le fonctionnement dans le cas de l'arbre ne change pas. Vous pouvez également ne pas hachage de l'ensemble de la structure, mais quelques-unes des caractéristiques telles que les objets de données de hachage plus les hashcodes d'un niveau en-dessous, il n'a pas à être O(n), il existe d'innombrables options ici. Je dis juste qu'il pourrait aider l'autre au début de la stratégie de sortie.Par curiosité, considérez-vous que les deux arbres à être égaux si leur contenu est identique, même si leur structure n'est pas? Par exemple, sont-ils égaux?
Ces arbres ont le même contenu dans le même ordre, mais parce que les structures sont différentes, par vos tests ne seraient pas égales.
Si vous voulez tester cette égalité, personnellement je venais de construire un itérateur sur l'arbre en utilisant dans l'ordre de la traversée et de l'itération à travers les arbres comparaison élément par élément.
Tout d'abord, je suis en train de faire quelques hypothèses générales. Ce sont des hypothèses qui sont valables pour la plupart des arbres, des classes de collection, mais c'est toujours la peine de vérifier:
En supposant que ces hypothèses sont correctes, puis l'approche que je suggère, c'est d':
this
ne peut pas être null). En outre, la JVM est très bon à l'optimisation des méthodes statiques.Ma mise en œuvre serait donc quelque chose comme:
Pour tout arbre de la manière la plus efficace de le représenter, de sorte que vous pouvez facilement vérifier l'égalité est la liste des parents - tenir un tableau dans lequel, pour chaque sommet, vous souvenez-vous de l'index de sa société mère(en fait tenir une paire - l'indice du père et de la valeur des données). Ensuite il vous suffit de
faudrait faire une comparaison des deux blocs continu de la mémoire.
Cela ne fonctionne que si l'arbre est statique(j'.e ne changent pas au fil du temps). Aussi il ne prend en compte les arbres à l'égalité si les sommets, les indices sont les mêmes dans les deux arbres.
Je crois que dans la plupart des cas, lorsque les deux instructions ci-dessus ne sont pas remplies, votre application devrait être à peu près aussi vite que vous pouvez obtenir.
EDIT: en fait, votre application peut être améliorée si vous suivez les conseils de Jon Skeet réponse(au moins return false dès que vous connaissez les arbres ne sont pas égales)
Le code donné ci-dessus serait de retour vrai pour les deux inégale des arbres avec la même racine valeurs. Je ne pense pas que ce est ce que vous voulez. Ne devrait-elle pas être:
if (!a==b) return false;
De cette façon, la méthode devait effectuer le reste de la vérifie.
(Ne pourrez pas vous connecter à partir d'ici pour une raison.)