Làm thế nào tôi có thể thực hiện một cây trong Python?


Câu trả lời:


232

bất cứ lúc nào

Tôi khuyên bạn nên https://pypi.python.org/pypi/anytree (Tôi là tác giả)

Thí dụ

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

Đặc trưng

anytree cũng có một API mạnh mẽ với:

  • tạo cây đơn giản
  • sửa đổi cây đơn giản
  • lặp trước đặt hàng cây
  • lặp lại sau khi đặt hàng cây
  • giải quyết các đường dẫn nút tương đối và tuyệt đối
  • đi bộ từ nút này sang nút khác.
  • kết xuất cây (xem ví dụ ở trên)
  • nút đính kèm / tách hookups

31
Đơn giản là câu trả lời tốt nhất, những người khác đang phát minh lại bánh xe.
Ondrej

66
Đây là hình thức tốt để tiết lộ rằng bạn là tác giả của gói mà bạn đề xuất trong câu trả lời của mình.
John Y

3
@ c0fec0de Em yêu anh !!!! Thư viện này thật tuyệt vời, thậm chí còn có chức năng hiển thị
layser

2
@Ondrej cũng các câu trả lời khác là phụ thuộc ít hơn và câu hỏi ban đầu đã hỏi về cấu trúc dữ liệu tích hợp. Trong khi anytreecó lẽ là một thư viện tuyệt vời, đây là một câu hỏi python, không phải là một câu hỏi Node.js.
Rob Rose

Tôi đã xem qua câu trả lời này thông qua Google. Thư viện này thực sự tốt đẹp. Tôi đặc biệt yêu thích khả năng sử dụng lớp mixin để tạo một cây của bất kỳ đối tượng nào!
Rÿck Nöthing

104

Python không có phạm vi cấu trúc dữ liệu "tích hợp" khá rộng như Java. Tuy nhiên, vì Python là động, nên một cây nói chung rất dễ tạo. Ví dụ: cây nhị phân có thể là:

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

Bạn có thể sử dụng nó như thế này:

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

109
Điều này không thực sự giải thích nhiều về việc thực hiện một cây hữu ích.
Mike Graham

14
Câu hỏi được gắn thẻ với Python3, sau đó không cần phải xuất phát class Treetừ đối tượng
cfi

3
@cfi Xuất phát từ objectđôi khi chỉ là một hướng dẫn: Nếu một lớp kế thừa từ không có lớp cơ sở nào khác, thì kế thừa rõ ràng từ đối tượng. Điều này cũng áp dụng cho các lớp lồng nhau. Xem Hướng dẫn về Phong cách Python của Google
Konrad Reiche

16
@platzhirsch: Vui lòng đọc và trích dẫn hoàn toàn hướng dẫn: Google chỉ ra rõ ràng rằng điều này là bắt buộc để mã Python 2 hoạt động như mong đợi và được đề xuất để cải thiện khả năng tương thích với Py3. Ở đây chúng ta đang nói về mã Py3. Không cần phải làm thêm, gõ di sản.
cfi

13
Đó là một cây nhị phân, không phải là một cây chung như yêu cầu.
Michael D Corner

49

Cây chung là một nút có 0 hoặc nhiều con, mỗi nút là một nút (cây) thích hợp. Nó không giống như cây nhị phân, chúng là các cấu trúc dữ liệu khác nhau, mặc dù cả hai đều có chung một số thuật ngữ.

Không có bất kỳ cấu trúc dữ liệu dựng sẵn nào cho các cây chung trong Python, nhưng nó dễ dàng được thực hiện với các lớp.

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

Thật tuyệt vời, điều này có thể dễ dàng được sử dụng như một biểu đồ quá! Vấn đề duy nhất mà tôi thấy là: Làm thế nào tôi có thể khác nút trái với nút phải?
Ângelo Polotto

3
Theo chỉ số trẻ em. Còn lại sẽ luôn là con [0] trong trường hợp đó.
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
Bạn có thể thêm một số ghi chú để giới thiệu mã của bạn và triển khai của bạn?
Michele Keyboardmico

Cảm ơn đã thực hiện Binary Tree hoàn chỉnh với các chức năng tiện ích. Vì nó là Python 2, tôi đã tạo ra một ý chính để triển khai Binary Tree (Py3) cho những người cần phiên bản Python 3.
CᴴᴀZ

16

Không có cây nào được xây dựng, nhưng bạn có thể dễ dàng xây dựng một cây bằng cách phân loại một loại Nút từ Danh sách và viết các phương thức truyền tải. Nếu bạn làm điều này, tôi đã thấy chia đôi hữu ích.

Ngoài ra còn có nhiều triển khai trên PyPi mà bạn có thể duyệt.

Nếu tôi nhớ chính xác, lib tiêu chuẩn Python không bao gồm các cấu trúc dữ liệu cây vì lý do tương tự mà thư viện lớp cơ sở .NET không: địa phương của bộ nhớ bị giảm, dẫn đến việc bỏ lỡ bộ nhớ cache nhiều hơn. Trên các bộ xử lý hiện đại, thường nhanh hơn khi chỉ mang một khối lớn bộ nhớ vào bộ đệm và cấu trúc dữ liệu "giàu con trỏ" phủ nhận lợi ích.


2
FYI: Các interwebs được dán đầy thù hận với Boost. Rõ ràng nó được coi là một nỗi đau lớn để giải quyết, đặc biệt là vì hỗ trợ cho nó đã bị ngừng. Vì vậy, tôi khuyên bạn nên tránh xa điều đó
thanh

Cảm ơn. Cá nhân tôi không gặp rắc rối gì, nhưng tôi không muốn đánh lạc hướng nên tôi đã xóa tham chiếu đó.
Justin R.

11

Tôi thực hiện một cây gốc như một từ điển {child:parent}. Vì vậy, ví dụ với nút gốc 0, một cây có thể trông như thế:

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

Cấu trúc này làm cho nó khá dễ dàng để đi lên dọc theo một đường dẫn từ bất kỳ nút nào đến gốc, có liên quan đến vấn đề tôi đang làm việc.


1
Đây là cách tôi đang xem xét thực hiện nó, cho đến khi tôi thấy câu trả lời. Mặc dù vì cây là cha mẹ có hai con và nếu bạn muốn đi xuống, bạn có thể làm được {parent:[leftchild,rightchild]}.
JFA

1
Một cách khác là sử dụng danh sách các danh sách trong đó phần tử đầu tiên (hoặc nhiều hơn) trong danh sách là giá trị nút và hai danh sách lồng nhau sau đây biểu thị các cây con trái và phải của nó (hoặc nhiều hơn cho cây n-ary).
pepr

9

Câu trả lời của Greg Hewgill là tuyệt vời nhưng nếu bạn cần nhiều nút hơn cho mỗi cấp độ, bạn có thể sử dụng danh sách | từ điển để tạo chúng: Và sau đó sử dụng phương pháp để truy cập chúng theo tên hoặc theo thứ tự (như 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

Bây giờ chỉ cần tạo một root và xây dựng nó lên: 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

Điều đó là đủ để bạn bắt đầu tìm ra cách để làm cho công việc này


Có một cái gì đó bị thiếu trong câu trả lời này, tôi đã thử giải pháp này trong 2 ngày qua và tôi nghĩ rằng bạn có một số luồng logic trong phương pháp thêm đối tượng. Tôi sẽ gửi câu trả lời của mình cho câu hỏi này, vui lòng kiểm tra và cho tôi biết nếu tôi có thể giúp đỡ.
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

hoạt động như một từ điển, nhưng cung cấp nhiều ký tự lồng nhau mà bạn muốn. Hãy thử như sau:

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

sẽ cung cấp một dict lồng nhau ... hoạt động như một cái cây thực sự.

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

... Nếu bạn đã có một lệnh, nó sẽ chuyển mỗi cấp thành một cây:

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

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

Theo cách này, bạn có thể tiếp tục chỉnh sửa / thêm / xóa từng cấp chính tả nếu muốn. Tất cả các phương pháp dict cho traversal vv, vẫn được áp dụng.


2
Có một lý do tại sao bạn chọn gia hạn dictthay vì defaultdict? Từ các thử nghiệm của tôi, mở rộng defaultdictthay vì dict và sau đó thêm self.default_factory = type(self)vào đầu init sẽ hoạt động theo cùng một cách.
Rob Rose

Tôi có lẽ đang thiếu một cái gì đó ở đây, làm thế nào để bạn điều hướng cấu trúc này? Chẳng hạn, rất khó để đi từ trẻ em sang cha mẹ, hoặc anh chị em
Stormsson

6

Tôi đã thực hiện cây bằng cách sử dụng các dicts lồng nhau. Nó khá dễ thực hiện và nó đã làm việc với tôi với các tập dữ liệu khá lớn. Tôi đã đăng một mẫu bên dưới và bạn có thể xem thêm tại mã 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

Tôi đã xuất bản một triển khai cây Python [3] trên trang web của mình: http://www.quesucede.com/page/show/id/python_3_tree_imâyation .

Hy vọng nó được sử dụng,

Ok, đây là mã:

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

Nếu ai đó cần một cách đơn giản hơn để làm điều đó, một cây chỉ là một danh sách lồng nhau đệ quy (vì tập hợp không thể băm được):

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

Trong đó mỗi nhánh là một cặp: [ object, [children] ]
và mỗi lá là một cặp:[ object, [] ]

Nhưng nếu bạn cần một lớp với các phương thức, bạn có thể sử dụng anytree.


1

Những hoạt động bạn cần? Thường có một giải pháp tốt trong Python bằng cách sử dụng dict hoặc danh sách với mô-đun bisect.

Có rất nhiều, rất nhiều cây thực hiện trên PyPI và nhiều loại cây gần như không quan trọng để tự thực hiện trong Python thuần túy. Tuy nhiên, điều này hiếm khi cần thiết.


0

Một cách thực hiện cây khác dựa trên câu trả lời của 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

Và một ví dụ về cách sử dụng nó:

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)

Mà nên xuất:

                        Nút gốc                        
     / / \              
Nút con 0 Nút con 1 Nút con 2        
                   | / \       
             Cháu 1.0 Cháu 2.0 Cháu 2.1 Cháu 2.1

0

Tôi đề nghị thư viện networkx .

NetworkX là gói Python để tạo, thao tác và nghiên cứu cấu trúc, động lực và chức năng của các mạng phức tạp.

Một ví dụ về xây dựng cây:

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

Tôi không chắc ý của bạn về " Cây chung " là gì,
nhưng thư viện cho phép mỗi nút trở thành bất kỳ đối tượng có thể băm nào và không có ràng buộc nào về số lượng con mà mỗi nút có.

Thư viện cũng cung cấp các thuật toán đồ thị liên quan đến cây và khả năng hiển thị .


-2

Nếu bạn muốn tạo cấu trúc dữ liệu cây thì trước tiên bạn phải tạo đối tượng treeEuity. Nếu bạn tạo đối tượng treeEuity, thì bạn có thể quyết định cách cây của bạn cư xử.

Để làm điều này sau đây là lớp TreeEuity:

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

Bây giờ, chúng ta phải sử dụng phần tử này để tạo cây, tôi đang sử dụng cây A * trong ví dụ này.

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)

Bạn có thể thêm / xóa bất kỳ phần tử nào khỏi đối tượng, nhưng làm cho cấu trúc trở nên phức tạp.


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

Điều này dường như không trả lời câu hỏi theo bất kỳ cách nào có thể đọc được.
AlBlue
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.