Bagaimana saya bisa mengimplementasikan pohon dengan Python?

Jawaban:

232

anytree

saya merekomendasi https://pypi.python.org/pypi/anytree (saya penulisnya)

Contoh

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

fitur

anytree juga memiliki API yang kuat dengan:

  • penciptaan pohon sederhana
  • modifikasi pohon sederhana
  • iterasi pohon pre-order
  • iterasi pohon post-order
  • menyelesaikan jalur simpul relatif dan absolut
  • berjalan dari satu simpul ke simpul lainnya.
  • rendering pohon (lihat contoh di atas)
  • simpul pasang / lepaskan hookup
c0fec0de
sumber
31
Cukup jawaban terbaik, orang lain menciptakan kembali roda.
Ondrej
66
Ini adalah bentuk yang baik untuk mengungkapkan bahwa Anda adalah pembuat paket yang Anda rekomendasikan dalam jawaban Anda.
John Y
3
@ c0fec0de Aku mencintaimu !!!! Perpustakaan ini luar biasa, bahkan memiliki fungsi visualisasi
layser
2
@Ondrej juga jawaban lain adalah ketergantungan kurang dan pertanyaan awal memang bertanya tentang built-in data-structure. Meskipun anytreemungkin merupakan perpustakaan yang hebat, ini adalah pertanyaan python, bukan pertanyaan Node.js.
Rob Rose
Saya menemukan jawaban ini melalui Google. Perpustakaan ini sangat bagus. Saya terutama menyukai kemampuan untuk menggunakan kelas mixin untuk membuat pohon dari objek apa pun!
Rÿck Nöthing
104

Python tidak memiliki cukup banyak struktur data "built-in" seperti halnya Java. Namun, karena Python dinamis, pohon umum mudah dibuat. Sebagai contoh, pohon biner mungkin:

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

Anda bisa menggunakannya seperti ini:

root = Tree()
root.data = "root"
root.left = Tree()
root.left.data = "left"
root.right = Tree()
root.right.data = "right"
Greg Hewgill
sumber
109
Ini tidak menjelaskan banyak hal tentang membuat implementasi pohon yang bermanfaat.
Mike Graham
14
Pertanyaan ini ditandai dengan Python3, tidak perlu diturunkan class Treedari objek saat itu
cfi
3
@cfi Berasal dari objectkadang-kadang hanya panduan: Jika suatu kelas mewarisi dari tidak ada kelas dasar lainnya, secara eksplisit mewarisi dari objek. Ini juga berlaku untuk kelas bersarang. Lihat Panduan Gaya Google Python
Konrad Reiche
16
@platzhirsch: Harap baca dan kutip panduan ini sepenuhnya: Google secara eksplisit menunjukkan bahwa ini diperlukan agar kode Python 2 berfungsi seperti yang diharapkan dan direkomendasikan untuk meningkatkan kompatibilitas dengan Py3. Di sini kita berbicara tentang kode Py3. Tidak perlu melakukan ekstra, mengetikkan warisan.
cfi
13
Itu pohon biner, bukan pohon umum seperti yang diminta.
Michael Dorner
49

Pohon generik adalah simpul dengan nol atau lebih anak, masing-masing simpul tepat (pohon). Itu tidak sama dengan pohon biner, mereka struktur data yang berbeda, meskipun keduanya memiliki beberapa terminologi.

Tidak ada struktur data bawaan untuk pohon generik di Python, tetapi mudah diimplementasikan dengan kelas.

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')])])
Rudá Moura
sumber
Luar biasa, ini juga bisa dengan mudah digunakan sebagai grafik! Satu-satunya masalah yang saya lihat adalah: Bagaimana saya bisa membedakan simpul kiri dari simpul kanan?
Ângelo Polotto
3
Menurut indeks anak-anak. Kiri akan selalu menjadi anak-anak [0] dalam kasus itu.
Freund Allein
38

Anda dapat mencoba:

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

Seperti yang disarankan di sini: https://gist.github.com/2012250

Ib33X
sumber
jika Anda ingin memperluas ke jumlah level yang sewenang-wenang, periksa: stackoverflow.com/a/43237270/511809
natbusa
ini membayangi hash fungsi bawaan.
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()
shivam garg
sumber
3
Bisakah Anda menambahkan hanya beberapa catatan untuk memperkenalkan kode Anda dan implementasi Anda?
Michele d'Amico
Terima kasih untuk implementasi Binary Tree yang lengkap dengan fungsi utilitas. Karena itu adalah Python 2, saya membuat intisari untuk implementasi Binary Tree (Py3) untuk orang yang membutuhkan versi Python 3.
CᴴᴀZ
16

Tidak ada pohon yang dibangun, tetapi Anda dapat dengan mudah membangunnya dengan mensubklasifikasikan jenis Node dari Daftar dan menulis metode traversal. Jika Anda melakukan ini, saya merasa membagi dua berguna.

Ada juga banyak implementasi pada PyPi yang dapat Anda telusuri.

Jika saya ingat dengan benar, lib standar Python tidak menyertakan struktur data pohon untuk alasan yang sama dengan pustaka kelas .NET tidak: lokalitas memori berkurang, mengakibatkan lebih banyak cache yang hilang. Pada prosesor modern biasanya lebih cepat hanya dengan membawa sebagian besar memori ke dalam cache, dan struktur data "pointer rich" meniadakan manfaatnya.

Justin R.
sumber
2
FYI: Jalinan jalinan dengan kebencian terhadap Boost. Rupanya itu seharusnya menjadi rasa sakit yang BESAR untuk dihadapi, terutama karena dukungan untuk itu telah dihentikan. Jadi saya akan merekomendasikan tinggal jauh dari itu
inspectorG4dget
Terima kasih. Saya tidak memiliki masalah apa pun secara pribadi, tetapi saya tidak ingin menyesatkan sehingga saya menghapus referensi itu.
Justin R.
11

Saya menerapkan pohon yang di-root sebagai kamus {child:parent}. Jadi misalnya dengan simpul root 0, pohon mungkin terlihat seperti itu:

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

Struktur ini membuatnya cukup mudah untuk naik sepanjang jalur dari sembarang simpul ke root, yang relevan untuk masalah yang sedang saya kerjakan.

mengais
sumber
1
Ini adalah cara saya mempertimbangkan untuk melakukannya, sampai saya melihat jawabannya. Meskipun karena pohon adalah orang tua dengan dua anak, dan jika Anda ingin turun, Anda dapat melakukannya {parent:[leftchild,rightchild]}.
JFA
1
Cara lain adalah dengan menggunakan daftar daftar di mana elemen pertama (atau lebih) dalam daftar adalah nilai node, dan dua daftar berikut bersarang mewakili subtree kiri dan kanannya (atau lebih untuk pohon n-ary).
pepr
9

Jawaban Greg Hewgill bagus, tetapi jika Anda membutuhkan lebih banyak node per level, Anda dapat menggunakan daftar | kamus untuk membuatnya: Dan kemudian gunakan metode untuk mengaksesnya baik dengan nama atau pesanan (seperti 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

Sekarang cukup buat root dan bangun: 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

Itu sudah cukup bagi Anda untuk mulai mencari tahu bagaimana membuat ini bekerja

Bruno
sumber
Ada sesuatu yang hilang dalam jawaban ini, saya mencoba solusi ini selama 2 hari terakhir dan saya pikir Anda memiliki beberapa aliran logis dalam metode penambahan objek. Saya akan mengirimkan jawaban saya untuk pertanyaan ini, silakan periksa dan beri tahu saya jika saya bisa membantu.
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

berfungsi sebagai kamus, tetapi sediakan banyak dict yang Anda inginkan. Coba yang berikut ini:

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

akan memberikan dict bersarang ... yang memang berfungsi sebagai pohon.

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

... Jika Anda sudah memiliki dict, itu akan melemparkan setiap level ke pohon:

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

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

Dengan cara ini, Anda dapat terus mengedit / menambah / menghapus setiap level dikt seperti yang Anda inginkan. Semua metode dict untuk traversal dll, masih berlaku.

natbusa
sumber
2
Apakah ada alasan mengapa Anda memilih untuk memperpanjang dictalih-alih defaultdict? Dari tes saya, memperluas defaultdictbukannya dict dan kemudian menambahkan self.default_factory = type(self)ke bagian atas init harus berfungsi dengan cara yang sama.
Rob Rose
Saya mungkin melewatkan sesuatu di sini, bagaimana Anda menavigasi struktur ini? tampaknya sangat sulit untuk beralih dari anak-anak ke orang tua, misalnya, atau saudara kandung
Stormsson
6

Saya telah mengimplementasikan pohon menggunakan dicts bersarang. Ini cukup mudah dilakukan, dan itu telah bekerja untuk saya dengan set data yang cukup besar. Saya telah memposting sampel di bawah ini, dan Anda dapat melihat lebih banyak di kode 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)
gaefan
sumber
5

Saya telah menerbitkan implementasi pohon Python [3] di situs saya: http://www.quesucede.com/page/show/id/python_3_tree_implementation .

Semoga bermanfaat,

Oke, ini kodenya:

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)
Brett Kromkamp
sumber
4

Jika seseorang membutuhkan cara yang lebih sederhana untuk melakukannya, sebuah pohon hanyalah daftar bersarang secara rekursif (karena set tidak dapat di hashable):

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

Di mana setiap cabang adalah pasangan: [ object, [children] ]
dan setiap daun adalah pasangan:[ object, [] ]

Tetapi jika Anda membutuhkan kelas dengan metode, Anda dapat menggunakan pohon anytree.

Hugo Trentesaux
sumber
1

Operasi apa yang Anda butuhkan? Seringkali ada solusi yang baik di Python menggunakan dict atau daftar dengan modul bisect.

Ada banyak, banyak implementasi pohon pada PyPI , dan banyak tipe pohon hampir sepele untuk mengimplementasikan diri Anda dengan Python murni. Namun, ini jarang diperlukan.

Mike Graham
sumber
0

Implementasi pohon lain secara longgar didasarkan pada jawaban 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

Dan contoh cara menggunakannya:

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)

Yang seharusnya menghasilkan:

                        Simpul akar                        
     / / \              
Simpul anak 0 Simpul anak 1 Simpul anak 2        
                   | / \       
             Grandchild 1.0 Grandchild 2.0 Grandchild 2.1
Solomon Ucko
sumber
0

Saya sarankan perpustakaan networkx .

NetworkX adalah paket Python untuk pembuatan, manipulasi, dan studi tentang struktur, dinamika, dan fungsi jaringan yang kompleks.

Contoh membangun pohon:

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

Saya tidak yakin apa yang Anda maksud dengan " General tree",
tetapi perpustakaan memungkinkan setiap node menjadi objek hashable , dan tidak ada batasan pada jumlah anak yang dimiliki setiap node.

Perpustakaan juga menyediakan algoritma grafik yang terkait dengan pohon dan kemampuan visualisasi .

Gal Avineri
sumber
-2

Jika Anda ingin membuat struktur data pohon maka pertama-tama Anda harus membuat objek treeElement. Jika Anda membuat objek treeElement, maka Anda dapat memutuskan bagaimana perilaku pohon Anda.

Untuk melakukan ini, berikut adalah kelas 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

Sekarang, kita harus menggunakan elemen ini untuk membuat pohon, saya menggunakan pohon A * dalam contoh ini.

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)

Anda dapat menambah / menghapus elemen apa pun dari objek, tetapi membuat strukturnya utuh.

MODUL MAULIK
sumber
-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)
Gagan Nirmal
sumber
Tampaknya ini tidak menjawab pertanyaan sama sekali dengan cara apa pun yang dapat dibaca.
AlBlue