Considérez la situation dans laquelle vous avez deux listes de nœuds dont vous savez que vous savez que l'une est une représentation d'une traversée pré-commande de certains arbres et l'autre une représentation d'une traversée d'une traversée du même arbre.
Je crois qu'il est possible de reconstruire l'arbre exactement de ces deux listes et je pense avoir un algorithme de le faire, mais je ne l'ai pas révélé. Comme cela fera partie d'un projet de maîtrise, je dois être absolument certain qu'il est possible et correct (mathématiquement éprouvé). Cependant, ce ne sera pas le centre du projet, alors je me demandais s'il y a une source là-bas (c'est-à-dire papier ou livre), je pouvais citer pour la preuve. (Peut-être à Taocp? Tout le monde connaît la section éventuellement?)
En bref, j'ai besoin d'un algorithme éprouvé dans une ressource utilitaire qui reconstruit un arbre de ses travers de pré-commandant.
Remarque: l'arborescence en question ne sera probablement pas binaire, ni équilibré, ou tout ce qui le rendrait trop facile.
NOTE2: L'utilisation de la liste de pré-commande ou de la pochette serait encore meilleure, mais je ne pense pas que cela soit possible.
Note3: Un nœud peut avoir une quantité d'enfants.
Note4: Je me soucie seulement de l'ordre des frères et sœurs. Gauche ou droite n'a pas d'importance quand il n'y a qu'un seul enfant.
Vous ne pouvez pas utiliser une seule liste, car vous n'aurez aucun sens de la profondeur de l'arbre. Ainsi, vous avez certainement besoin de deux ou plusieurs listes.
Voici ma tentative d'une solution:
Utilisez votre parcours pré-commande comme moyen de connaître la commande des données. Cela a du sens parce que vous savez que le premier nœud est le sommet et vous savez que les données plus loin à gauche de la traversée appartiennent à gauche de l'arborescence, etc.
Votre trershable de commande post-commande peut déterminer la profondeur de l'arbre. Par exemple, disons que j'ai une structure comme celle-ci:
1
2 5 6
3 4 7
Where 2 is the parent of 3 and 4, and 5 is the parent of 7.
Preorder: 1 2 3 4 5 7 6
Postorder: 3 4 2 7 5 6 1
Nous savons que nous commençons par 1, car c'est le premier noeud de la traversée pré-commande. Ensuite, nous examinons le numéro suivant, 2. Dans la commande postale, car le numéro 2 vient avant le nœud 1, nous savons que 2 doit être un enfant de 1. Ensuite, nous regardons ensuite 3. 3 vient avant 2 ans et donc 3 est un enfant de 2. 4 est avant 2 ans mais après 3, nous savons donc que 4 est un enfant de 2 mais pas un enfant de 3. etc.
Maintenant, cela peut ne pas fonctionner si les nœuds ne sont pas uniques, mais à tout le moins de son départ à une solution.
EDIT: L'ordre des enfants est préservé avec cette solution, simplement en sachant la commande des nœuds via la traversée de pré-commande, puis en sachant la structure via la traversée du postpert.
EDIT2: La preuve peut être utilisée ici: http://eeeexplore.eeee.org/xplore/login.jsp?url=http% 3A% 2f% 2FeeEEExplore.eeee.org% 2fiel2% 2f215% 2f626% 2f00017225.pdf% 3Farnumber% 3D17225 & AuthDecision = -2
Je pense que vous devez acheter le document, cependant ...
Voici une preuve écrite présentée comme une solution:
http://www14.informatik.tu-muenchen.de/lehre/2007ws/fa-cse/tatudials/taturial09-solutions.pdf
Pré-commandant et posteur ne définissent pas de manière unique un arbre.
En général, un seul trersharsal d'arbre ne définit pas de manière unique la structure de l'arbre. Par exemple, comme nous l'avons vu, pour les arbres suivants, un rendement des inondérations traférés [1,2,3,4,5,6].
4 3
/ \ / \
2 5 2 5
/ \ \ / / \
1 3 6 1 4 6
La même ambiguïté est présente pour les traversées pré-commandes et post-poste. La traversée de pré-commande pour le premier arbre ci-dessus est [4,2,1,3,5,6]. Voici un arbre différent avec le même trershasel pré-commande.
4
/ \
2 1
/ \
3 6
\
5
De même, nous pouvons facilement construire un autre arbre dont le travertisseur postérieur [1,3,2,6,5,4] correspond à celui du premier arbre ci-dessus.
Considérons un arbre arbitraire [~ # ~] t [~ # ~] en tant que quadruple (A, B, C , D ), où A est le noeud racine, B est le noeud racine de la première enfance, C est un vecteur de tous les enfants non vides de B, et D est un vecteur de tous les frères et soeurs non vides de B. Les éléments de C et D sont les arbres eux-mêmes.
N'importe lequel de A, B, [~ # ~ # ~] c [~ # ~] et [~ # ~] d [~ # ~ ~] peut être vide. Si B est vide, il faut donc être [~ # ~ ~] c [~ # ~] et D ; Si un, alors tout.
Étant donné que les nœuds sont uniques, les jeux de nœuds contenus n'importe où dans C et [~ # ~] d [~ # ~ ~] sont disjoint, et ni non plus a ou B.
Fonctions pré () et post () générer des séquences ordonnées de la forme:
pré (T) = [A, B, pré ( C ) , avant ( D ) ]
poste (T) = [ après ( C ) , B, poste ( D ) , A]
lorsque la fonction appliquée sur un vecteur est définie comme une concaténation des séquences résultant de l'application de la fonction à chaque élément à son tour.
Considère maintenant les cas:
Dans tous les cas, nous pouvons séparer sans ambiguïté les membres des deux séquences de sortie dans les sous-séquences appropriées, en utilisant A et B (si présent) en tant que délimiteurs.
La question est alors, peut-on également partitionner les séquences de vecteur? Si nous pouvons, chacun peut être traité de récursivité et nous avons terminé.
Etant donné que le résultat de pré () sera toujours une chaîne de séquences à partir de avec des noeuds A et le résultat de post () sera toujours une chaîne de séquences se terminant avec des noeuds a, on peut en effet les diviser, à condition que les noeuds A sont jamais vide.
C'est là que le processus tombe dans le cas d'arbres binaires (ou en tout) avec des enfants fixes pouvant être vides de manière indépendante. Dans notre cas, cependant, nous avons défini [~ # ~ # ~] c [~ # ~] et [~ # ~] d [~ # ~ ~] pour ne contenir que non Nœuds mémorisants, et la reconstruction est donc garantie de fonctionner.
Euh, je pense que oui, de toute façon. De toute évidence, c'est juste un argument, pas une preuve formelle!
Les traverses de pré-commande et de post-poste sont suffisantes pour reconstruire l'arborescence, en supposant que les nœuds ne soient nommés de manière unique. La clé pour créer les algorithmes à le faire est de comprendre que
X est un ancêtre de Y IFF X précède Y dans la pré-commande et est après y dans le pooléron.
Compte tenu de cela, nous pouvons toujours trouver tous les descendants de tout nœud. Les descendants de x suivent toujours immédiatement X dans la pré-commande et précèdent X dans le posteur. Donc, une fois que nous savons que nous sommes intéressés à produire le sous-arbre enraciné à X, nous pouvons extraire le trershasel pré-commande et postal pour le sous-arbre enraciné à X. Cela conduit naturellement à un algorithme récursif, une fois que nous réalisons que le noeud immédiatement après X doit être Son enfant le plus à gauche, s'il s'agit d'un descendant du tout.
Il existe également une implémentation basée sur une pile, qui iTère à travers les nœuds pré-commandes et continue de la pile tous les nœuds qui sont candidats à être le parent direct du nœud Pré-commande suivant. Pour chaque nœud de pré-commande, popez-vous à plusieurs reprises tous les nœuds de la pile qui ne sont pas des parents du nœud de pré-commande suivant. Faites savoir ce nœud un enfant du nœud supérieur sur la pile et poussez l'enfant sur la pile.
Comme cela a déjà souligné par d'autres, un arbre binaire ne peut pas être reconstruit en utilisant uniquement une traversée avant et après l'ordre. Un seul noeud enfant a des traversiers ambigus qui ne peuvent pas identifier s'il est laissé ou à droite de l'enfant. Pensez à suivre les traverser pré-commandant et post-poste: Pré-commande: A, B Postard b, A
Il peut produire les deux arbres suivants
a A \/B B Il n'est tout simplement pas possible de savoir si B est un enfant gauche ou droit à gauche sans aucune information supplémentaire comme l'inadaptation Traversal.
Créez un arbre binaire avec cette restriction qui a au moins un nœud que ce nœud n'a qu'un seul enfant (à droite ou à gauche, il n'y a pas de différence).
Maintenant, écrivez ses listes pré-commandes et postérieures. Ensuite, essayez de reconstruire l'arborescence de ces listes. Et vous vous rendez compte que sur ce nœud, vous ne pouvez pas décider que son enfant a raison ou de rester à gauche.
Il n'est pas possible de construire un arbre binaire général des traverses de pré-commande et de postonnaissance (voir ceci). Mais si sachez que l'arbre binaire est plein, nous pouvons construire l'arbre sans ambiguïté. Comprend cela avec l'aide de l'exemple suivant.
Considérons les deux tableaux donnés comme pré [] = {1, 2, 4, 8, 9, 5, 3, 6, 7} et post [] = {8, 9, 4, 5, 2, 6, 7 , 3, 1}; En avant [], l'élément le plus à gauche est la racine de l'arbre. Étant donné que l'arbre est plein et que la taille de la matrice est supérieure à 1. La valeur à côté de 1 en avant [] doit être laissée à la racine. Nous savons donc que 1 est la racine et 2 est laissé enfant. Comment trouver tous les nœuds de la sous-arbre gauche? Nous savons que 2 est la racine de tous les nœuds de la sous-arbre gauche. Tous les nœuds avant 2 en poste [] doivent être à gauche sous-arbre. Maintenant, nous savons que 1 est la racine, les éléments {8, 9, 4, 5, 2} sont dans le sous-arbre gauche, et les éléments {6, 7, 3} sont dans un sous-arbre droit.
1
/ \
/ \
{8, 9, 4, 5, 2} {6, 7, 3}
Nous suivons récursivement l'approche ci-dessus et obtenez l'arbre suivant.
1
/ \
2 3
/ \ / \
4 5 6 7/\
[.____] 8 9