Malheureusement, vous ne nous fournissez pas le Tree
classe, mais supposons qu'il est quelque chose comme:
class Tree(object):
def __init__(self):
self.data = None
self.nextkey = 0
self.thedict = {}
lorsque de nouveaux nœuds sont insérés
avec les différents attributs étant mis à jour avec précision. Maintenant, alors que vous parlez de "l'adresse enregistrée dans le dictionnaire", il est clair que la valeur du dict n'est PAS "une adresse" - mais plutôt un objet Node (si vous définissez une méthode spéciale dans votre nœud, vous pouvez pour voir cela d'une manière plus claire, ce que vous voyez est la représentation par défaut, utilisée pour tous les objets Python dont le type ne définit pas ou n'hérite pas __repr__
). Par conséquent, l'échange de sous-arbres aléatoires entre deux arborescences différentes requiert uniquement la mise à jour de toutes les nombreuses informations redondantes que vous conservez (et qui doit être ALL sync).En passant, il serait plus simple si de telles mises à jour étaient des méthodes de Tree et/ou Node et donc utilisables pour différents types de "edit" (insertion, suppression, etc), plutôt qu'incroyable dans une fonction qui effectue les mises à jour dans le cadre d'un échange aléatoire - c'est une bonne pratique OO. Mais, c'est un peu un problème secondaire. Vous ne nous dites pas exactement comment fonctionne l'attribut branch
, je suppose qu'il s'agit d'une chaîne, 'gauche' ou 'droite' selon le cas (ou Aucun s'il n'y a pas de parent, c'est-à-dire un noeud racine).
Pour supprimer une sous-arborescence, vous devez mettre à jour: le nœud parent, en définissant sur None son attribut approprié; la racine du sous-arbre, définissant à None ses attributs parents et branches; AND the Tree, supprimant cette entrée de l'attribut thedict
de l'arborescence. Vous devrez également vous souvenir de ce que le parent et la branche étaient afin d'être en mesure d'insérer un autre sous-arbre à cet endroit. Par conséquent ...:
def removeSubtreeFromTree(tree, keyindict):
subtreenode = tree.thedict.pop(keyindict)
parent, branch = subtreenode.parent, subtreenode.branch
# a sanity chech can't hurt...;-)
assert getattr(parent, branch) is subtreenode
subtreenode.parent, subtreenode.branch = None, None
setattr(parent, branch, None)
return subtreenode, parent, branch
Maintenant, pour ajouter un nouveau sous-arbre à un parent et la branche donnée dans un arbre est plus simple:
def addNewSubtree(tree, subtreenode, parent, branch):
# sanity checks R us
assert getattr(parent, branch) is None
assert subtreenode.parent is None
assert subtreenode.branch is None
setattr(parent, branch, subtreenode)
subtreenode.parent = parent
subtreenode.branch = branch
tree.thedict[tree.nextkey] = subtreenode
tree.nextkey += 1
Remarque vous ne pouvez pas simplement réutiliser les clés précédentes: il pourrait y avoir être un "conflit" (en supposant que les clés ne sont uniques que dans un seul Arbre donné ... si vous les avez rendues uniques globalement à la place, alors vous pourriez en effet les réutiliser).
Enfin, mettre ces deux opérations et un peu plus ensemble peut être fait. Si vous n'avez jamais besoin d '"échanger" la racine même d'un arbre, c'est plus simple (pas de cas particulier pour traiter un sous-arbre sans parent ...) donc je vais supposer que (si vous voulez plus de généralité, vous devrez coder les cas particuliers tatillonnes - idéalement après refactoring choses à des méthodes comme je l'ai déjà suggéré, -) ...:
def randomNonrootSubtree(tree):
# we're in trouble if the tree ONLY has a root w/no really SUB trees;-)
assert len(tree.thedict) > 1
while True:
thekey = random.choice(tree.thedict.keys())
subtree = tree.thedict[thekey]
if subtree.parent: return thekey
et enfin ...:
def theSwapper(t1, t2):
k1 = randomNonrootSubtree(t1)
k2 = randomNonrootSubtree(t2)
st1, p1, b1 = removeSubtreeFromTree(t1, k1)
st2, p2, b2 = removeSubtreeFromTree(t2, k2)
addNewSubtree(t1, st2, p1, b1)
addNewSubtree(t2, st1, p2, b2)
Notez que, contrairement à ce Alex , suppose qu'aucun nœud n'est la racine de son arbre. – Anon
(Pour gérer cette possibilité, il est possible d'ajouter des cas elif aux mises à jour parentes, de sorte que les elses n'attrapent pas les cas "right" et root. – Anon