Ce qui suit est un O(n log n) algorithme de travail pour les graphes dans laquelle chaque enfant a au plus un parent (EDIT: cet algorithme ne s'étend pas aux deux parents de cas avec O(n log n) de la performance). Il est intéressant de noter que, je crois, le rendement peut être amélioré à O(n log(niveau max de l'étiquette)) avec un supplément de travail.
Un parent cas:
Pour chaque nœud x, en sens inverse l'ordre topologique, créer un arbre de recherche binaire T_x que est strictement croissante à la fois dans la date de naissance et le nombre de générations retiré de x. (T_x contient le premier enfant né c1 dans le sous-graphe de l'ascendance graphe de racine x, ainsi que la suivante plus tôt né c2 dans ce sous-graphe tel que c2 "grande niveau des grands-parents' est strictement plus grande que celle de la c1, avec la prochaine premières né c3 dans ce sous-graphe tels que la c3 niveau est strictement plus grande que celle de c2, etc.) Pour créer T_x, nous fusionner précédemment construit des arbres T_w où w est un enfant de x (ils sont déjà construits, parce que nous sommes une itération inverse l'ordre topologique).
Si nous faisons attention à la façon dont nous effectuons les fusionne, on peut montrer que le coût total de ces fusions est O(n log n) pour l'ensemble de l'ascendance graphique. L'idée clé est à noter qu'après chaque fusion, tout au plus un nœud de chaque niveau survit dans la fusion de l'arbre. Nous associons à chaque arbre T_w un potentiel de h(w) log n, où h(w) est égale à la longueur du plus long chemin de w à une feuille.
Lorsque nous fusionner les arbres de l'enfant T_w pour créer T_x, nous détruire ' tous les arbres de l'T_w, libérant tout le potentiel qu'ils stocker pour une utilisation dans la construction de l'arbre T_x; et nous créer une nouvelle arborescence T_x avec (log n)(h(x)) potentiel. Ainsi, notre objectif est de passer au plus O((log n)(sum_w(h(w)) - h(x) + constante), le temps de créer T_x des arbres T_w de sorte que le coût amorti de la fusion sera seulement O(log n). Ceci peut être réalisé en choisissant l'arbre T_w tels que h(w) est maximale en tant que point de départ pour T_x et puis de modifier T_w pour créer T_x. Après un tel choix est fait pour T_x, nous fusionner les uns des autres arbres, un par un, dans T_x avec un algorithme qui est similaire à l'algorithme de fusion de deux arbres binaires.
Essentiellement, la fusion est réalisée par une itération sur chaque nœud y en T_w, recherche pour y prédécesseur de z par date de naissance, et puis en insérant y en T_x si c'est plus de niveaux retiré de x de z; alors, si z a été inséré dans T_x, nous recherchons pour le nœud de T_x du niveau le plus bas qui est strictement plus grand que z est de niveau, et épissure hors de la période de nœuds pour maintenir l'invariant que T_x est commandé strictement à la fois par la date de naissance et le niveau. Cela coûte O(log n) pour chaque nœud dans T_w, et il y a au plus O(h(w)) les nœuds T_w, de sorte que le coût total de la fusion de tous les arbres est en O((log n)(sum_w(h(w))), sommation sur l'ensemble des enfants w sauf pour l'enfant du w' tel que h(w') est maximale.
Nous stockons le niveau associé à chaque élément de T_x dans les services auxiliaires de champ de chaque nœud dans l'arbre. Nous avons besoin de cette valeur, de sorte que nous pouvons déterminer le niveau réel de x une fois que nous avons construit T_x. (Comme un détail technique, nous avons effectivement le magasin de la différence de chaque nœud de niveau avec celle de son parent dans T_x afin que nous puissions rapidement incrémenter les valeurs pour tous les nœuds de l'arbre. C'est un standard BST truc.)
C'est tout. Nous indiquons simplement que le potentiel initial est 0 et la dernière potentiel est positif donc la somme de l'amorti limites est une limite supérieure sur le coût total de toutes les fusions dans l'ensemble de l'arbre. Nous trouver l'étiquette de chaque nœud x une fois que nous créons de la BST T_x en binaire de la recherche pour le dernier élément dans T_x qui est né avant le x est mort au coût O(log n).
Pour améliorer le liés à O(n log(niveau max de l'étiquette)), vous pouvez paresseusement fusionner les arbres, seulement de fusionner les premiers éléments de l'arbre qui est nécessaire pour fournir la solution pour le nœud actuel. Si vous utilisez un BST qui exploite la localité de référence, tel qu'un splay tree, vous pouvez profiter de la ci-dessus lié.
Heureusement, l'algorithme ci-dessus et l'analyse est au moins assez claire à suivre. Juste un commentaire si vous avez besoin d'une clarification.