Come posso implementare un albero in Python?


Risposte:


233

anytree

Raccomando https://pypi.python.org/pypi/anytree (sono l'autore)

Esempio

from anytree import Node, RenderTree

udo = Node("Udo")
marc = Node("Marc", parent=udo)
lian = Node("Lian", parent=marc)
dan = Node("Dan", parent=udo)
jet = Node("Jet", parent=dan)
jan = Node("Jan", parent=dan)
joe = Node("Joe", parent=dan)

print(udo)
Node('/Udo')
print(joe)
Node('/Udo/Dan/Joe')

for pre, fill, node in RenderTree(udo):
    print("%s%s" % (pre, node.name))
Udo
├── Marc
   └── Lian
└── Dan
    ├── Jet
    ├── Jan
    └── Joe

print(dan.children)
(Node('/Udo/Dan/Jet'), Node('/Udo/Dan/Jan'), Node('/Udo/Dan/Joe'))

Caratteristiche

anytree ha anche una potente API con:

  • semplice creazione di alberi
  • semplice modifica dell'albero
  • iterazione dell'albero pre-ordine
  • iterazione dell'albero post-ordine
  • risolvere percorsi di nodi relativi e assoluti
  • camminando da un nodo all'altro.
  • rendering ad albero (vedi esempio sopra)
  • nodo collegare / scollegare collegamenti

31
Semplicemente la risposta migliore, altri stanno reinventando la ruota.
Ondrej,

66
È una buona forma per rivelare che sei l'autore del pacchetto che stai raccomandando nella tua risposta.
John Y,

3
@ c0fec0de Ti amo !!!! Questa libreria è incredibile, ha anche una funzionalità di visualizzazione
data

2
@Ondrej bene le altre risposte sono meno dipendenze e la domanda originale faceva delle strutture di dati integrate. Sebbene anytreesia probabilmente un'ottima libreria, questa è una domanda su Python, non una domanda su Node.js.
Rob Rose

Ho trovato questa risposta tramite Google. Questa libreria è davvero carina. In particolare, adoro la capacità di usare la classe mixin per creare un albero di qualsiasi oggetto!
Rÿck Nöthing

104

Python non ha l'ampia gamma di strutture di dati "incorporate" come Java. Tuttavia, poiché Python è dinamico, è facile creare un albero generale. Ad esempio, un albero binario potrebbe essere:

class Tree:
    def __init__(self):
        self.left = None
        self.right = None
        self.data = None

Puoi usarlo in questo modo:

root = Tree()
root.data = "root"
root.left = Tree()
root.left.data = "left"
root.right = Tree()
root.right.data = "right"

109
Questo non spiega molto su come realizzare un'implementazione ad albero utile.
Mike Graham,

14
La domanda è taggata con Python3, quindi non è necessario derivare class Treedall'oggetto
cfi,

3
@cfi Derivare da objectè talvolta solo una linea guida: se una classe eredita da nessun'altra classe base, eredita esplicitamente dall'oggetto. Questo vale anche per le classi nidificate. Vedi la Guida allo stile di Google Python
Konrad Reiche,

16
@platzhirsch: leggi e cita completamente le linee guida: Google sottolinea esplicitamente che ciò è necessario affinché il codice Python 2 funzioni come previsto e consigliato per migliorare la compatibilità con Py3. Qui stiamo parlando del codice Py3. Non è necessario eseguire ulteriori digitazioni legacy.
cfi,

13
Quello è un albero binario, non generale come richiesto.
Michael Dorner,

49

Un albero generico è un nodo con zero o più figli, ognuno un nodo (albero) proprio. Non è lo stesso di un albero binario, sono diverse strutture di dati, sebbene entrambe condividano un po 'di terminologia.

Non esiste alcuna struttura di dati incorporata per alberi generici in Python, ma è facilmente implementabile con le classi.

class Tree(object):
    "Generic tree node."
    def __init__(self, name='root', children=None):
        self.name = name
        self.children = []
        if children is not None:
            for child in children:
                self.add_child(child)
    def __repr__(self):
        return self.name
    def add_child(self, node):
        assert isinstance(node, Tree)
        self.children.append(node)
#    *
#   /|\
#  1 2 +
#     / \
#    3   4
t = Tree('*', [Tree('1'),
               Tree('2'),
               Tree('+', [Tree('3'),
                          Tree('4')])])

Incredibile, questo può essere facilmente utilizzato anche come grafico! L'unico problema che ho riscontrato è: come posso differenziare il nodo sinistro dal nodo destro?
Angelo Polotto,

3
Per indice dei bambini. In questo caso rimarranno sempre i bambini [0].
Freund Allein,


20
class Node:
    """
    Class Node
    """
    def __init__(self, value):
        self.left = None
        self.data = value
        self.right = None

class Tree:
    """
    Class tree will provide a tree as well as utility functions.
    """

    def createNode(self, data):
        """
        Utility function to create a node.
        """
        return Node(data)

    def insert(self, node , data):
        """
        Insert function will insert a node into tree.
        Duplicate keys are not allowed.
        """
        #if tree is empty , return a root node
        if node is None:
            return self.createNode(data)
        # if data is smaller than parent , insert it into left side
        if data < node.data:
            node.left = self.insert(node.left, data)
        elif data > node.data:
            node.right = self.insert(node.right, data)

        return node


    def search(self, node, data):
        """
        Search function will search a node into tree.
        """
        # if root is None or root is the search data.
        if node is None or node.data == data:
            return node

        if node.data < data:
            return self.search(node.right, data)
        else:
            return self.search(node.left, data)



    def deleteNode(self,node,data):
        """
        Delete function will delete a node into tree.
        Not complete , may need some more scenarion that we can handle
        Now it is handling only leaf.
        """

        # Check if tree is empty.
        if node is None:
            return None

        # searching key into BST.
        if data < node.data:
            node.left = self.deleteNode(node.left, data)
        elif data > node.data:
            node.right = self.deleteNode(node.right, data)
        else: # reach to the node that need to delete from BST.
            if node.left is None and node.right is None:
                del node
            if node.left == None:
                temp = node.right
                del node
                return  temp
            elif node.right == None:
                temp = node.left
                del node
                return temp

        return node






    def traverseInorder(self, root):
        """
        traverse function will print all the node in the tree.
        """
        if root is not None:
            self.traverseInorder(root.left)
            print root.data
            self.traverseInorder(root.right)

    def traversePreorder(self, root):
        """
        traverse function will print all the node in the tree.
        """
        if root is not None:
            print root.data
            self.traversePreorder(root.left)
            self.traversePreorder(root.right)

    def traversePostorder(self, root):
        """
        traverse function will print all the node in the tree.
        """
        if root is not None:
            self.traversePostorder(root.left)
            self.traversePostorder(root.right)
            print root.data


def main():
    root = None
    tree = Tree()
    root = tree.insert(root, 10)
    print root
    tree.insert(root, 20)
    tree.insert(root, 30)
    tree.insert(root, 40)
    tree.insert(root, 70)
    tree.insert(root, 60)
    tree.insert(root, 80)

    print "Traverse Inorder"
    tree.traverseInorder(root)

    print "Traverse Preorder"
    tree.traversePreorder(root)

    print "Traverse Postorder"
    tree.traversePostorder(root)


if __name__ == "__main__":
    main()

3
Puoi aggiungere solo alcune note per introdurre il tuo codice e la tua implementazione?
Michele d'Amico,

Grazie per l'implementazione completa dell'albero binario con funzioni di utilità. Dato che è Python 2, ho creato una sintesi per l' implementazione di Binary Tree (Py3) per le persone che necessitano di una versione di Python 3.
CᴴᴀZ,

16

Non ci sono alberi incorporati, ma puoi costruirne facilmente una sottoclasse da un tipo di nodo da Elenco e scrivere i metodi di attraversamento. Se lo fai, ho trovato bisect utile.

Ci sono anche molte implementazioni su PyPi che puoi sfogliare.

Se ricordo bene, la lib standard di Python non include strutture di dati ad albero per lo stesso motivo per cui la libreria di classi base di .NET non lo fa: la localizzazione della memoria è ridotta, con conseguenti maggiori mancate cache. Sui processori moderni di solito è più veloce portare un grosso pezzo di memoria nella cache e strutture di dati "puntatore ricco" annullano il vantaggio.


2
FYI: Le interwebs sono intonacate di odio contro Boost. Apparentemente dovrebbe essere un dolore ENORME da affrontare, soprattutto da quando il supporto è stato sospeso. Quindi consiglierei di starne alla larga
inspector

Grazie. Personalmente non ho avuto problemi, ma non voglio fuorviare, quindi ho rimosso quel riferimento.
Justin R.

11

Ho implementato un albero radicato come dizionario {child:parent}. Quindi, ad esempio con il nodo radice 0, un albero potrebbe apparire così:

tree={1:0, 2:0, 3:1, 4:2, 5:3}

Questa struttura ha reso abbastanza facile andare verso l'alto lungo un percorso da qualsiasi nodo alla radice, il che era rilevante per il problema su cui stavo lavorando.


1
Questo è il modo in cui stavo considerando di farlo, fino a quando non ho visto la risposta. Anche se un albero è un genitore con due figli e se vuoi andare giù, puoi farlo {parent:[leftchild,rightchild]}.
JFA,

1
Un altro modo consiste nell'utilizzare elenchi di elenchi in cui il primo (o più) elemento nell'elenco è il valore del nodo e i seguenti due elenchi nidificati rappresentano i suoi sottotitoli sinistro e destro (o più per l'albero n-ary).
pepr

9

La risposta di Greg Hewgill è ottima, ma se hai bisogno di più nodi per livello puoi usare un elenco | dizionario per crearli: E quindi usare il metodo per accedervi per nome o ordine (come id)

class node(object):
    def __init__(self):
        self.name=None
        self.node=[]
        self.otherInfo = None
        self.prev=None
    def nex(self,child):
        "Gets a node by number"
        return self.node[child]
    def prev(self):
        return self.prev
    def goto(self,data):
        "Gets the node by name"
        for child in range(0,len(self.node)):
            if(self.node[child].name==data):
                return self.node[child]
    def add(self):
        node1=node()
        self.node.append(node1)
        node1.prev=self
        return node1

Ora basta creare una radice e costruirla: ex:

tree=node()  #create a node
tree.name="root" #name it root
tree.otherInfo="blue" #or what ever 
tree=tree.add() #add a node to the root
tree.name="node1" #name it

    root
   /
child1

tree=tree.add()
tree.name="grandchild1"

       root
      /
   child1
   /
grandchild1

tree=tree.prev()
tree=tree.add()
tree.name="gchild2"

          root
           /
        child1
        /    \
grandchild1 gchild2

tree=tree.prev()
tree=tree.prev()
tree=tree.add()
tree=tree.name="child2"

              root
             /   \
        child1  child2
       /     \
grandchild1 gchild2


tree=tree.prev()
tree=tree.goto("child1") or tree=tree.nex(0)
tree.name="changed"

              root
              /   \
         changed   child2
        /      \
  grandchild1  gchild2

Questo dovrebbe essere sufficiente per iniziare a capire come farlo funzionare


C'è qualcosa che manca in questa risposta, ho provato questa soluzione negli ultimi 2 giorni e penso che tu abbia un flusso logico nel metodo di aggiunta dell'oggetto. Invierò la mia risposta a questa domanda, per favore controlla quella e fammi sapere se posso aiutare.
MAULIK MODI,

8
class Tree(dict):
    """A tree implementation using python's autovivification feature."""
    def __missing__(self, key):
        value = self[key] = type(self)()
        return value

    #cast a (nested) dict to a (nested) Tree class
    def __init__(self, data={}):
        for k, data in data.items():
            if isinstance(data, dict):
                self[k] = type(self)(data)
            else:
                self[k] = data

funziona come un dizionario, ma fornisce tutti i dadi nidificati che desideri. Prova quanto segue:

your_tree = Tree()

your_tree['a']['1']['x']  = '@'
your_tree['a']['1']['y']  = '#'
your_tree['a']['2']['x']  = '$'
your_tree['a']['3']       = '%'
your_tree['b']            = '*'

produrrà un dict nidificato ... che funziona davvero come un albero.

{'a': {'1': {'x': '@', 'y': '#'}, '2': {'x': '$'}, '3': '%'}, 'b': '*'}

... Se hai già un dict, lancerà ogni livello su un albero:

d = {'foo': {'amy': {'what': 'runs'} } }
tree = Tree(d)

print(d['foo']['amy']['what']) # returns 'runs'
d['foo']['amy']['when'] = 'now' # add new branch

In questo modo, puoi continuare a modificare / aggiungere / rimuovere ogni livello di dict come desideri. Si applicano ancora tutti i metodi dict per l'attraversamento, ecc.


2
C'è un motivo per cui hai scelto di estendere dictinvece di defaultdict? Dai miei test, l'estensione defaultdictinvece di dict e l'aggiunta self.default_factory = type(self)all'inizio di init dovrebbe funzionare allo stesso modo.
Rob Rose

probabilmente mi sto perdendo qualcosa qui, come si naviga questa struttura? sembra molto difficile passare dai bambini ai genitori, per esempio, o fratelli
Stormsson,

6

Ho implementato alberi usando dadi annidati. È abbastanza facile da fare e ha funzionato per me con set di dati piuttosto grandi. Ho pubblicato un esempio di seguito e puoi vedere di più sul codice di Google

  def addBallotToTree(self, tree, ballotIndex, ballot=""):
    """Add one ballot to the tree.

    The root of the tree is a dictionary that has as keys the indicies of all 
    continuing and winning candidates.  For each candidate, the value is also
    a dictionary, and the keys of that dictionary include "n" and "bi".
    tree[c]["n"] is the number of ballots that rank candidate c first.
    tree[c]["bi"] is a list of ballot indices where the ballots rank c first.

    If candidate c is a winning candidate, then that portion of the tree is
    expanded to indicate the breakdown of the subsequently ranked candidates.
    In this situation, additional keys are added to the tree[c] dictionary
    corresponding to subsequently ranked candidates.
    tree[c]["n"] is the number of ballots that rank candidate c first.
    tree[c]["bi"] is a list of ballot indices where the ballots rank c first.
    tree[c][d]["n"] is the number of ballots that rank c first and d second.
    tree[c][d]["bi"] is a list of the corresponding ballot indices.

    Where the second ranked candidates is also a winner, then the tree is 
    expanded to the next level.  

    Losing candidates are ignored and treated as if they do not appear on the 
    ballots.  For example, tree[c][d]["n"] is the total number of ballots
    where candidate c is the first non-losing candidate, c is a winner, and
    d is the next non-losing candidate.  This will include the following
    ballots, where x represents a losing candidate:
    [c d]
    [x c d]
    [c x d]
    [x c x x d]

    During the count, the tree is dynamically updated as candidates change
    their status.  The parameter "tree" to this method may be the root of the
    tree or may be a sub-tree.
    """

    if ballot == "":
      # Add the complete ballot to the tree
      weight, ballot = self.b.getWeightedBallot(ballotIndex)
    else:
      # When ballot is not "", we are adding a truncated ballot to the tree,
      # because a higher-ranked candidate is a winner.
      weight = self.b.getWeight(ballotIndex)

    # Get the top choice among candidates still in the running
    # Note that we can't use Ballots.getTopChoiceFromWeightedBallot since
    # we are looking for the top choice over a truncated ballot.
    for c in ballot:
      if c in self.continuing | self.winners:
        break # c is the top choice so stop
    else:
      c = None # no candidates left on this ballot

    if c is None:
      # This will happen if the ballot contains only winning and losing
      # candidates.  The ballot index will not need to be transferred
      # again so it can be thrown away.
      return

    # Create space if necessary.
    if not tree.has_key(c):
      tree[c] = {}
      tree[c]["n"] = 0
      tree[c]["bi"] = []

    tree[c]["n"] += weight

    if c in self.winners:
      # Because candidate is a winner, a portion of the ballot goes to
      # the next candidate.  Pass on a truncated ballot so that the same
      # candidate doesn't get counted twice.
      i = ballot.index(c)
      ballot2 = ballot[i+1:]
      self.addBallotToTree(tree[c], ballotIndex, ballot2)
    else:
      # Candidate is in continuing so we stop here.
      tree[c]["bi"].append(ballotIndex)

5

Ho pubblicato un'implementazione dell'albero di Python [3] sul mio sito: http://www.quesucede.com/page/show/id/python_3_tree_implementation .

Spero sia utile,

Ok, ecco il codice:

import uuid

def sanitize_id(id):
    return id.strip().replace(" ", "")

(_ADD, _DELETE, _INSERT) = range(3)
(_ROOT, _DEPTH, _WIDTH) = range(3)

class Node:

    def __init__(self, name, identifier=None, expanded=True):
        self.__identifier = (str(uuid.uuid1()) if identifier is None else
                sanitize_id(str(identifier)))
        self.name = name
        self.expanded = expanded
        self.__bpointer = None
        self.__fpointer = []

    @property
    def identifier(self):
        return self.__identifier

    @property
    def bpointer(self):
        return self.__bpointer

    @bpointer.setter
    def bpointer(self, value):
        if value is not None:
            self.__bpointer = sanitize_id(value)

    @property
    def fpointer(self):
        return self.__fpointer

    def update_fpointer(self, identifier, mode=_ADD):
        if mode is _ADD:
            self.__fpointer.append(sanitize_id(identifier))
        elif mode is _DELETE:
            self.__fpointer.remove(sanitize_id(identifier))
        elif mode is _INSERT:
            self.__fpointer = [sanitize_id(identifier)]

class Tree:

    def __init__(self):
        self.nodes = []

    def get_index(self, position):
        for index, node in enumerate(self.nodes):
            if node.identifier == position:
                break
        return index

    def create_node(self, name, identifier=None, parent=None):

        node = Node(name, identifier)
        self.nodes.append(node)
        self.__update_fpointer(parent, node.identifier, _ADD)
        node.bpointer = parent
        return node

    def show(self, position, level=_ROOT):
        queue = self[position].fpointer
        if level == _ROOT:
            print("{0} [{1}]".format(self[position].name,
                                     self[position].identifier))
        else:
            print("\t"*level, "{0} [{1}]".format(self[position].name,
                                                 self[position].identifier))
        if self[position].expanded:
            level += 1
            for element in queue:
                self.show(element, level)  # recursive call

    def expand_tree(self, position, mode=_DEPTH):
        # Python generator. Loosly based on an algorithm from 'Essential LISP' by
        # John R. Anderson, Albert T. Corbett, and Brian J. Reiser, page 239-241
        yield position
        queue = self[position].fpointer
        while queue:
            yield queue[0]
            expansion = self[queue[0]].fpointer
            if mode is _DEPTH:
                queue = expansion + queue[1:]  # depth-first
            elif mode is _WIDTH:
                queue = queue[1:] + expansion  # width-first

    def is_branch(self, position):
        return self[position].fpointer

    def __update_fpointer(self, position, identifier, mode):
        if position is None:
            return
        else:
            self[position].update_fpointer(identifier, mode)

    def __update_bpointer(self, position, identifier):
        self[position].bpointer = identifier

    def __getitem__(self, key):
        return self.nodes[self.get_index(key)]

    def __setitem__(self, key, item):
        self.nodes[self.get_index(key)] = item

    def __len__(self):
        return len(self.nodes)

    def __contains__(self, identifier):
        return [node.identifier for node in self.nodes
                if node.identifier is identifier]

if __name__ == "__main__":

    tree = Tree()
    tree.create_node("Harry", "harry")  # root node
    tree.create_node("Jane", "jane", parent = "harry")
    tree.create_node("Bill", "bill", parent = "harry")
    tree.create_node("Joe", "joe", parent = "jane")
    tree.create_node("Diane", "diane", parent = "jane")
    tree.create_node("George", "george", parent = "diane")
    tree.create_node("Mary", "mary", parent = "diane")
    tree.create_node("Jill", "jill", parent = "george")
    tree.create_node("Carol", "carol", parent = "jill")
    tree.create_node("Grace", "grace", parent = "bill")
    tree.create_node("Mark", "mark", parent = "jane")

    print("="*80)
    tree.show("harry")
    print("="*80)
    for node in tree.expand_tree("harry", mode=_WIDTH):
        print(node)
    print("="*80)

4

Se qualcuno ha bisogno di un modo più semplice per farlo, un albero è solo un elenco annidato in modo ricorsivo (poiché set non è hash):

[root, [child_1, [[child_11, []], [child_12, []]], [child_2, []]]]

Dove ogni ramo è una coppia: [ object, [children] ]
e ogni foglia è una coppia:[ object, [] ]

Ma se hai bisogno di una classe con metodi, puoi usare anytree.


1

Di quali operazioni hai bisogno? C'è spesso una buona soluzione in Python usando un dict o una lista con il modulo bisect.

Ci sono molte, molte implementazioni di alberi su PyPI e molti tipi di alberi sono quasi banali da implementare in Python puro. Tuttavia, questo è raramente necessario.


0

Un'altra implementazione dell'albero è vagamente basata sulla risposta di Bruno :

class Node:
    def __init__(self):
        self.name: str = ''
        self.children: List[Node] = []
        self.parent: Node = self

    def __getitem__(self, i: int) -> 'Node':
        return self.children[i]

    def add_child(self):
        child = Node()
        self.children.append(child)
        child.parent = self
        return child

    def __str__(self) -> str:
        def _get_character(x, left, right) -> str:
            if x < left:
                return '/'
            elif x >= right:
                return '\\'
            else:
                return '|'

        if len(self.children):
            children_lines: Sequence[List[str]] = list(map(lambda child: str(child).split('\n'), self.children))
            widths: Sequence[int] = list(map(lambda child_lines: len(child_lines[0]), children_lines))
            max_height: int = max(map(len, children_lines))
            total_width: int = sum(widths) + len(widths) - 1
            left: int = (total_width - len(self.name) + 1) // 2
            right: int = left + len(self.name)

            return '\n'.join((
                self.name.center(total_width),
                ' '.join(map(lambda width, position: _get_character(position - width // 2, left, right).center(width),
                             widths, accumulate(widths, add))),
                *map(
                    lambda row: ' '.join(map(
                        lambda child_lines: child_lines[row] if row < len(child_lines) else ' ' * len(child_lines[0]),
                        children_lines)),
                    range(max_height))))
        else:
            return self.name

E un esempio di come usarlo:

tree = Node()
tree.name = 'Root node'
tree.add_child()
tree[0].name = 'Child node 0'
tree.add_child()
tree[1].name = 'Child node 1'
tree.add_child()
tree[2].name = 'Child node 2'
tree[1].add_child()
tree[1][0].name = 'Grandchild 1.0'
tree[2].add_child()
tree[2][0].name = 'Grandchild 2.0'
tree[2].add_child()
tree[2][1].name = 'Grandchild 2.1'
print(tree)

Che dovrebbe produrre:

                        Nodo radice                        
     / / \              
Nodo figlio 0 Nodo figlio 1 Nodo figlio 2        
                   | / \       
             Grandchild 1.0 Grandchild 2.0 Grandchild 2.1

0

Suggerisco la libreria networkx .

NetworkX è un pacchetto Python per la creazione, la manipolazione e lo studio della struttura, della dinamica e delle funzioni di reti complesse.

Un esempio di costruzione di un albero:

import networkx as nx
G = nx.Graph()
G.add_edge('A', 'B')
G.add_edge('B', 'C')
G.add_edge('B', 'D')
G.add_edge('A', 'E')
G.add_edge('E', 'F')

Non sono sicuro di cosa si intenda per " albero generale ",
ma la libreria consente a ciascun nodo di essere qualsiasi oggetto hash , e non vi è alcun vincolo sul numero di figli di ciascun nodo.

La libreria fornisce anche algoritmi grafici relativi ad alberi e capacità di visualizzazione .


-2

Se si desidera creare una struttura dati ad albero, per prima cosa è necessario creare l'oggetto treeElement. Se crei l'oggetto treeElement, puoi decidere come si comporta il tuo albero.

Per fare ciò, la seguente è la classe TreeElement:

class TreeElement (object):

def __init__(self):
    self.elementName = None
    self.element = []
    self.previous = None
    self.elementScore = None
    self.elementParent = None
    self.elementPath = []
    self.treeLevel = 0

def goto(self, data):
    for child in range(0, len(self.element)):
        if (self.element[child].elementName == data):
            return self.element[child]

def add(self):

    single_element = TreeElement()
    single_element.elementName = self.elementName
    single_element.previous = self.elementParent
    single_element.elementScore = self.elementScore
    single_element.elementPath = self.elementPath
    single_element.treeLevel = self.treeLevel

    self.element.append(single_element)

    return single_element

Ora, dobbiamo usare questo elemento per creare l'albero, in questo esempio sto usando un albero A *.

class AStarAgent(Agent):
# Initialization Function: Called one time when the game starts
def registerInitialState(self, state):
    return;

# GetAction Function: Called with every frame
def getAction(self, state):

    # Sorting function for the queue
    def sortByHeuristic(each_element):

        if each_element.elementScore:
            individual_score = each_element.elementScore[0][0] + each_element.treeLevel
        else:
            individual_score = admissibleHeuristic(each_element)

        return individual_score

    # check the game is over or not
    if state.isWin():
        print('Job is done')
        return Directions.STOP
    elif state.isLose():
        print('you lost')
        return Directions.STOP

    # Create empty list for the next states
    astar_queue = []
    astar_leaf_queue = []
    astar_tree_level = 0
    parent_tree_level = 0

    # Create Tree from the give node element
    astar_tree = TreeElement()
    astar_tree.elementName = state
    astar_tree.treeLevel = astar_tree_level
    astar_tree = astar_tree.add()

    # Add first element into the queue
    astar_queue.append(astar_tree)

    # Traverse all the elements of the queue
    while astar_queue:

        # Sort the element from the queue
        if len(astar_queue) > 1:
            astar_queue.sort(key=lambda x: sortByHeuristic(x))

        # Get the first node from the queue
        astar_child_object = astar_queue.pop(0)
        astar_child_state = astar_child_object.elementName

        # get all legal actions for the current node
        current_actions = astar_child_state.getLegalPacmanActions()

        if current_actions:

            # get all the successor state for these actions
            for action in current_actions:

                # Get the successor of the current node
                next_state = astar_child_state.generatePacmanSuccessor(action)

                if next_state:

                    # evaluate the successor states using scoreEvaluation heuristic
                    element_scored = [(admissibleHeuristic(next_state), action)]

                    # Increase the level for the child
                    parent_tree_level = astar_tree.goto(astar_child_state)
                    if parent_tree_level:
                        astar_tree_level = parent_tree_level.treeLevel + 1
                    else:
                        astar_tree_level += 1

                    # create tree for the finding the data
                    astar_tree.elementName = next_state
                    astar_tree.elementParent = astar_child_state
                    astar_tree.elementScore = element_scored
                    astar_tree.elementPath.append(astar_child_state)
                    astar_tree.treeLevel = astar_tree_level
                    astar_object = astar_tree.add()

                    # If the state exists then add that to the queue
                    astar_queue.append(astar_object)

                else:
                    # Update the value leaf into the queue
                    astar_leaf_state = astar_tree.goto(astar_child_state)
                    astar_leaf_queue.append(astar_leaf_state)

È possibile aggiungere / rimuovere qualsiasi elemento dall'oggetto, ma rendere intatta la struttura.


-4
def iterative_bfs(graph, start):
    '''iterative breadth first search from start'''
    bfs_tree = {start: {"parents":[], "children":[], "level":0}}
    q = [start]
    while q:
        current = q.pop(0)
        for v in graph[current]:
            if not v in bfs_tree:
                bfs_tree[v]={"parents":[current], "children":[], "level": bfs_tree[current]["level"] + 1}
                bfs_tree[current]["children"].append(v)
                q.append(v)
            else:
                if bfs_tree[v]["level"] > bfs_tree[current]["level"]:
                    bfs_tree[current]["children"].append(v)
                    bfs_tree[v]["parents"].append(current)

Ciò non sembra rispondere alla domanda affatto in alcun modo leggibile.
AlBlue,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.