Як я можу реалізувати дерево в Python?


204

Я намагаюся побудувати загальне дерево.

Чи є вбудовані структури даних в Python для їх реалізації?



Посилання @GrvTyagi не працює.
Тоні Лукас

Відповіді:


232

будь-яке дерево

Рекомендую https://pypi.python.org/pypi/anytree (я автор)

Приклад

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'))

Особливості

anytree також має потужний API з:

  • просте створення дерева
  • проста модифікація дерева
  • попереднє замовлення ітерації дерева
  • ітерація дерева після замовлення
  • вирішити відносні та абсолютні шляхи вузлів
  • ходьба від одного вузла до іншого.
  • надання дерева (див. приклад вище)
  • вузол приєднання / від'єднання підключень

31
Просто найкраща відповідь, інші винаходять колесо.
Ондрей

66
Добре розкрити, що ви автор пакету, який ви рекомендуєте у своїй відповіді.
Джон Y

3
@ c0fec0de я тебе люблю !!!! Ця бібліотека дивовижна, навіть має функцію візуалізації
лайсер

2
@Ondrej добре, що інші відповіді - це залежність менше, і первісне питання ставив питання про вбудовані структури даних. Хоча anytreeце, мабуть, чудова бібліотека, це питання python, а не питання Node.js.
Роб Роуз

Я натрапив на цю відповідь через Google. Ця бібліотека справді приємна. Мені особливо подобається вміння використовувати клас mixin для виготовлення дерева з будь-якого предмета!
Rÿck Nöthing

104

Python не має досить широкого спектру "вбудованих" структур даних, як це робить Java. Однак, оскільки Python динамічний, загальне дерево легко створити. Наприклад, двійкове дерево може бути:

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

Ви можете використовувати його так:

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

109
Це насправді не дуже пояснює створення корисної реалізації дерева.
Майк Грехем

14
Питання позначене Python3, class Treeтоді об'єкта не потрібно виходити
cfi

3
@cfi Виведення з objectіноді є лише керівництвом: Якщо клас успадковує від інших базових класів, явно успадковує від об'єкта. Це стосується і вкладених класів. Дивіться посібник зі стилів Google Python
Konrad Reiche

16
@platzhirsch: Будь ласка, прочитайте та цитуйте вказівки повністю: Google прямо вказує, що це потрібно для того, щоб код Python 2 працював так, як очікувалося, і рекомендував покращити сумісність з Py3. Тут ми говоримо про код Py3. Не потрібно робити зайві, застарілі введення тексту.
cfi

13
Це двійкове дерево, а не загальне, як просили.
Майкл Дорнер

49

Родове дерево - це вузол з нульовою чи більшою кількістю дітей, кожен з яких є правильним (деревним) вузлом. Це не те саме, що двійкове дерево, вони різні структури даних, хоча обидва поділяють деяку термінологію.

Існує не будь-яка вбудована структура даних для загальних дерев в Python, але вона легко реалізується з класами.

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')])])

Дивно, але це також можна легко використовувати як графік! Єдина проблема, яку я бачив, це: як я можу відрізняти лівий вузол від правого вузла?
Венло Полотто

3
За індексом дітей. Зліва завжди будуть діти [0].
Аллейн

38

Ви можете спробувати:

from collections import defaultdict
def tree(): return defaultdict(tree)
users = tree()
users['harold']['username'] = 'hrldcpr'
users['handler']['username'] = 'matthandlersux'

Як тут запропоновано: https://gist.github.com/2012250


якщо ви хочете продовжити на довільну кількість рівнів перевірки: stackoverflow.com/a/43237270/511809
natbusa

це затінює вбудований функціональний хеш.
Tritium21

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
Чи можете ви додати лише кілька приміток, щоб представити свій код та вашу реалізацію?
Мішель д'Аміко,

Дякуємо за повну реалізацію Бінарного дерева з корисними функціями. Оскільки це Python 2, я створив суть для реалізації Binary Tree (Py3) для людей, які потребують версії Python 3.
CᴴᴀZ

16

Тут немає вбудованих дерев, але їх можна легко сконструювати, підкласуючи тип вузла зі списку та записавши методи обходу. Якщо ви це зробите, я вважаю бісект корисним.

На PyPi також є багато реалізацій, які ви можете переглядати.

Якщо я правильно пам’ятаю, стандартна вкладка Python не включає структури даних дерев з тієї ж причини, що і бібліотека базового класу .NET: локальність пам’яті зменшена, що призводить до помилок кешу. У сучасних процесорах зазвичай швидше просто внести великий об'єм пам'яті в кеш, а структури даних, багаті на покажчики, заперечують користь.


2
FYI: Інтервету обмазані ненавистю до Boost. Мабуть, з цим треба боротися з ВЕЛИЧИМ болем, тим більше, що підтримка для нього припинена. Тому я б рекомендував триматися подалі від цього
inspectorG4dget

Дякую. У мене особисто не було проблем, але я не хочу вводити в оману, тому я видалив цю посилання.
Джастін Р.

11

Я реалізував вкорінене дерево як словник {child:parent}. Так, наприклад, з кореневим вузлом 0дерево може виглядати так:

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

Ця структура дозволила досить легко піднятися вгору по шляху від будь-якого вузла до кореня, що було актуально для проблеми, над якою я працював.


1
Це так, як я розглядав це зробити, поки не побачив відповіді. Хоча оскільки дерево - це батько з двома дітьми, і якщо ви хочете спуститися, можете зробити {parent:[leftchild,rightchild]}.
JFA

1
Інший спосіб полягає у використанні списків списків, де перший (або більше) елемент у списку - це значення вузла, а наступні вкладені два списки представляють його ліві та праві підряди (або більше для n-арного дерева).
пепр

9

Відповідь Грега Хьюгілла чудова, але якщо вам потрібно більше вузлів на рівні, ви можете використовувати список | словник для їх створення: а потім скористайтеся методом доступу до них або по імені, або за порядком (як ідентифікатор)

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

Тепер просто створіть корінь і складіть його: 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

Цього має бути достатньо, щоб ви почали з'ясовувати, як зробити цю роботу


Щось у цій відповіді бракує, я пробував це рішення протягом останніх 2 днів, і я думаю, у вас є певний логічний потік у методі додавання об’єктів. Я надішлю свою відповідь на це запитання, будь ласка, перевірте це і повідомте мені, чи можу я допомогти.
МАУЛІК МОДІ

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

працює як словник, але надає стільки вкладених диктів, які ви хочете. Спробуйте наступне:

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']            = '*'

видасть вкладений дікт ... який справді працює як дерево.

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

... Якщо у вас вже є диктант, він передасть кожен рівень дереву:

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

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

Таким чином, ви можете продовжувати редагувати / додавати / видаляти кожен рівень платівки за своїм бажанням. Усі методи вибору для обходу тощо все ще застосовуються.


2
Чи є причина, чому ви вирішили продовжити dictзамість defaultdict? З моїх тестів, розширення defaultdictзамість dict і додавання self.default_factory = type(self)до вершини init повинно функціонувати так само.
Роб Роуз

Мені, напевно, чогось тут не вистачає, як ви орієнтуєтесь у цій структурі? здається, дуже важко перейти від дітей до батьків, наприклад, або братів і сестер
Stormsson

6

Я реалізував дерева, використовуючи вкладені дикти. Це зробити досить просто, і він працював для мене з досить великими наборами даних. Я опублікував зразок нижче, і ви можете побачити більше за кодом 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

Я опублікував реалізацію дерева Python [3] на своєму веб-сайті: http://www.quesucede.com/page/show/id/python_3_tree_implementation .

Сподіваюся, це корисно,

Гаразд, ось код:

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

Якщо комусь потрібен простіший спосіб зробити це, дерево є лише рекурсивно вкладеним списком (оскільки набір не є доступним для підключення):

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

Де кожна гілка - пара: [ object, [children] ]
і кожен лист - пара:[ object, [] ]

Але якщо вам потрібен клас з методами, ви можете використовувати anytree.


1

Які операції вам потрібні? У Python часто є хорошим рішенням з використанням dict або списку з бісект-модулем.

На PyPI є багато, багато реалізацій дерев , і багато типів дерев майже тривіально реалізувати себе в чистому Python. Однак це рідко необхідно.


0

Ще одна реалізація дерева, заснована на відповіді Бруно :

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

І приклад того, як ним користуватися:

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)

Який має вивести:

                        Кореневий вузол                        
     / / \              
Дочірній вузол 0 Дочірній вузол 1 Дитячий вузол 2        
                   | / \       
             Онук 1.0 Онук 2.0 Онук 2.1

0

Я пропоную бібліотеку networkx .

NetworkX - це пакет Python для створення, маніпулювання та вивчення структури, динаміки та функцій складних мереж.

Приклад побудови дерева:

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')

Я не впевнений, що ви маєте на увазі під « загальним деревом»,
але бібліотека дає змогу кожному вузлу бути будь-яким об'єктом , що перемикається , і немає обмежень щодо кількості дітей, які має кожен вузол.

Бібліотека також пропонує графічні алгоритми, пов’язані з деревами та можливостями візуалізації .


-2

Якщо ви хочете створити структуру даних про дерево, тоді спочатку потрібно створити об'єкт treeElement. Якщо ви створюєте об'єкт treeElement, ви можете вирішити, як поводиться ваше дерево.

Для цього слід виконати наступний клас 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

Тепер ми повинні використовувати цей елемент для створення дерева, я використовую дерево 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)

Ви можете додати / видалити будь-які елементи з об’єкта, але зробити так, щоб структура працювала.


-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)

Здається, це зовсім не дає відповіді на запитання.
AlBlue
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.