12
votes

Algorithme d'ancêtre commun le plus bas

J'ai donc cherché à mettre en œuvre un algorithme d'ancêtres communs le plus bas. J'ai examiné de nombreux algorithmes différents (principalement des variations de la solution ou des variations de Trajan de la RMQ).

J'utilise un arbre non binaire. Mon arbre changera souvent entre les requêtes et donc le pré-traitement ne serait pas nécessairement utile. L'arbre ne doit pas avoir plus de 50-75 nœuds. Ce que je me demande, c'est si je devrais vous soucier d'utiliser leurs algorithmes ou de rester avec moi-même.

mon algorithme xxx


1 commentaires

Hmm, je ne vois pas comment c'est une vraie question. Quel type de réponse attendez-vous à recevoir?


6 Réponses :


4
votes

Pour un arbre qui petit, je ne me dérangerais pas de mettre en œuvre quelque chose de plus complexe. Votre solution a l'air bien, bien que la complexité temporelle soit carrée en termes de hauteur de l'arbre. Si vous pouvez facilement implémenter un définir (la plupart des langues l'ont intégrée), alors l'algorithme pourrait être modifié,

  1. traverser du premier noeud jusqu'à la racine et collectez tous les nœuds dans un ensemble
  2. traverser du deuxième noeud jusqu'à la racine et vérifiez si le nœud actuel existe dans cet ensemble. Si c'est le cas, c'est l'ancêtre commun.

    En outre, cet algorithme suppose qu'un nœud peut être son propre ancêtre. Sinon, vous devriez légèrement modifier l'algorithme. Considérez cet exemple, xxx

    lorsque vous essayez de trouver l'ancêtre commun le plus bas de B, etc., cet algorithme signalerait B, qui peut ou non être vrai en fonction de la façon dont vous Définir l'ancêtre.


0 commentaires

3
votes

sans regarder les détails de l'un ou l'autre des algorithmes, je suggère de regarder à quel point l'efficacité de ces algorithmes est importante de votre application globale et de la manière dont l'effort serait nécessaire pour mettre en œuvre un autre algorithme.

Combien de fois cet algorithme sera-t-il exécuté dans le fonctionnement normal (ou stressé) de votre application? Cela fera-t-il attendre l'utilisateur plus longtemps que nécessaire? Les autres algorithmes d'un ordre de grandeur différent sont-ils plus rapidement que ceux? (Une personne familière avec les algorithmes peut vous donner une réponse plus détaillée à ce sujet.)

Je pense qu'il ne vaut pas la peine d'optimiser un peu de code, à moins que vous ne voyiez que des résultats importants (certaines personnes se sentent fortement si une optamisation prématurée est la racine de tout mal )


0 commentaires

2
votes

Votre algorithme est quadratique, mais il peut facilement être fabriqué linéaire.

Utilisez simplement HASHTABLE (I.E. SET) pour ParentNode , au lieu de la liste. Vérification donc si un nœud est dans parentnode sera o (1) au lieu de o (n) . .


0 commentaires

17
votes

Comme d'autres personnes ont mentionné, votre algorithme est actuellement quadratique. Cela peut ne pas être un problème pour un jeu de données aussi petit que 50-75 nœuds, mais dans tous les cas, il est simple de la modifier en temps linéaire sans utiliser de jeux ni de hashtables, juste en enregistrant le chemin complet de la racine pour chaque nœud, puis En descendant de la racine et à la recherche du premier nœud différent. Le nœud précédent (qui est le parent commun de ces 2 nœuds différents) est alors la LCA: xxx

edit 27/5/2012: gérer le cas dans Lequel un nœud est descendu de l'autre, qui autrement entraînerait une tentative de pop () une pile vide. Merci à damné de pointer cela. (J'ai également compris qu'il suffit de suivre un seul oldnode .)


6 commentaires

Modification: dans des langues comme Java, POP () peut lancer ELTOLSTACKEXCEPTION, qui devrait être traitée par une manipulation d'exception ou en vérifiant les tailles des deux piles avant de sauter.


@Damned: En réalité, ce n'est pas nécessaire, car le fait que nœud1 et nœud2 appartiennent au même arborescence garantit qu'un ancêtre commun sera trouvé dans le dernier pendant < / Code> Boucle - Aucun de ces appels vers POP () peut éventuellement échouer.


L'exception se produira toujours si nous avons un nœud pour être le descendant de l'autre. Prenez une paire parent-enfant par exemple.


@damned: Vous avez tout à fait raison, mes excuses. Je vais mettre à jour dans un moment pour résoudre ce problème.


Néanmoins, elle ne manipule pas correctement pour un nœud est descendue d'autre que je pense. Say List1 a 3 éléments et liste2 a 2 éléments. Après avoir fonctionné pendant deux fois, cela a un problème.


@NRK: En supposant que vous signiez le cas lorsque nœud1 est un enfant de node2 : Ce cas semble fonctionner pour moi lorsque j'écris les états après chaque étape. Le tandis que est testé 3 fois: la première fois, nœud1 et nœud2 sont les deux null , la deuxième fois Ils sont tous deux égaux au nœud racine, la troisième fois qu'ils sont égaux au 2e nœud du chemin de la racine (ce sera nœud2 ) mais parentnode2 est vide donc les sorties de la boucle et si (nœud1 == nœud2) renvoyer le nœud1 réussit. Notez que nœud1 est modifié à l'intérieur de la fonction - il ne retournera pas la valeur d'origine transmise.



2
votes

Je viens d'écrire un article de blog sur la manière dont je devais mettre en œuvre mon propre algorithme pour ce problème, mais étendu à un ensemble de nœuds d'une longueur arbitraire. Vous pouvez le trouver ici (avec une explication graphique étape par étape de la façon dont cela fonctionne)

http://bio4j.com/blog/2012/02/finding-the-lowest-Common-ChoFeTor-Of-se-Of-ncbi-taxonomy-nodes-with-bio4j/ < / a>

acclamations,

Pablo


1 commentaires

Le lien direct ne fonctionne pas pour moi, cependant, si vous êtes Google, vous y arriverez.



1
votes

J'ai une solution simpliste trier les deux éléments et le plus bas être laissé et le plus élevé est juste visiter la racine DEF RECURSE (racine) retourner nil si root.empty? Si laissé <= root && droite> = racine racine de retour Elsif quitte <= root && droite <= root recueil (root.left) autre recueil (racine.right) fin

Donc, cela va vérifier chaque traversé Le problème soumis à O (log n) temps pour la moyenne et la pire et o (journal


0 commentaires