[PYTHON] 어떻게 파이썬에서 트리를 구현할 수 있습니까? Java와 같이 파이썬에 내장 된 데이터 구조가 있습니까?
PYTHON어떻게 파이썬에서 트리를 구현할 수 있습니까? Java와 같이 파이썬에 내장 된 데이터 구조가 있습니까?
나는 일반적인 나무를 만들려고 노력하고있다. 트리를 구현하기 위해 파이썬에 내장 된 데이터 구조가 있습니까?
해결법
-
==============================
1.나는 https://pypi.python.org/pypi/anytree를 추천한다.
나는 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가 있습니다.
-
==============================
2.파이썬에는 자바처럼 광범위한 "기본 제공"데이터 구조가 없습니다. 그러나 파이썬은 동적이기 때문에 일반 트리를 쉽게 만들 수 있습니다. 예를 들어, 이진 트리는 다음과 같을 수 있습니다.
파이썬에는 자바처럼 광범위한 "기본 제공"데이터 구조가 없습니다. 그러나 파이썬은 동적이기 때문에 일반 트리를 쉽게 만들 수 있습니다. 예를 들어, 이진 트리는 다음과 같을 수 있습니다.
class Tree(object): 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"
-
==============================
3.일반 트리는 0 개 이상의 자식이있는 노드로 각 노드는 적절한 (트리) 노드입니다. 이진 트리와 동일하지는 않습니다. 서로 다른 데이터 구조를 사용합니다.
일반 트리는 0 개 이상의 자식이있는 노드로 각 노드는 적절한 (트리) 노드입니다. 이진 트리와 동일하지는 않습니다. 서로 다른 데이터 구조를 사용합니다.
파이썬에서 일반 트리에 대한 데이터 구조는 내장되어 있지 않지만 클래스로 쉽게 구현됩니다.
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')])])
-
==============================
4.당신은 시도 할 수 있습니다:
당신은 시도 할 수 있습니다:
from collections import defaultdict def tree(): return defaultdict(tree) users = tree() users['harold']['username'] = 'hrldcpr' users['handler']['username'] = 'matthandlersux'
여기에 제안 된대로 : https://gist.github.com/2012250
-
==============================
5.트리가 내장되어 있지는 않지만, List에서 Node 유형을 서브 클래스 화하고 순회 방식을 작성하여 쉽게 트리를 작성할 수 있습니다. 당신이 그렇게한다면, 나는 bisect가 유용하다는 것을 발견했다.
트리가 내장되어 있지는 않지만, List에서 Node 유형을 서브 클래스 화하고 순회 방식을 작성하여 쉽게 트리를 작성할 수 있습니다. 당신이 그렇게한다면, 나는 bisect가 유용하다는 것을 발견했다.
탐색 할 수있는 PyPi에 대한 많은 구현도 있습니다.
올바르게 기억한다면 Python 표준 라이브러리에는 .NET 기본 클래스 라이브러리와 같은 이유로 트리 데이터 구조가 포함되지 않습니다. 메모리의 지역성이 줄어들어 캐시가 더 많이 손실됩니다. 현대의 프로세서에서는 대용량의 메모리를 캐시에 가져 오는 것이 일반적으로 빠르며 "포인터가 많은"데이터 구조는 이점을 무효화합니다.
-
==============================
6.
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.traversePreorder(root.left) self.traversePreorder(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()
-
==============================
7.사전 {child : parent}로 루트 트리를 구현했습니다. 예를 들어 루트 노드 0을 사용하면 트리가 다음과 같이 보일 수 있습니다.
사전 {child : parent}로 루트 트리를 구현했습니다. 예를 들어 루트 노드 0을 사용하면 트리가 다음과 같이 보일 수 있습니다.
tree={1:0, 2:0, 3:1, 4:2, 5:3}
이 구조 덕분에 노드에서 루트까지의 경로를 따라 쉽게 올라갈 수있었습니다. 이는 내가 작업하고 있던 문제와 관련이있었습니다.
-
==============================
8.Greg Hewgill의 답변은 훌륭하지만 수준별로 노드가 더 필요하면 목록을 작성하여 사전을 만들 수 있습니다. 그런 다음 메서드를 사용하여 이름이나 순서 (ID와 같은)로 액세스 할 수 있습니다.
Greg Hewgill의 답변은 훌륭하지만 수준별로 노드가 더 필요하면 목록을 작성하여 사전을 만들 수 있습니다. 그런 다음 메서드를 사용하여 이름이나 순서 (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
이제 루트를 만들고 빌드하십시오. 전의:
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
그게 당신이이 일을하는 법을 알아내는 데 충분할 거에요.
-
==============================
9.중첩 된 dicts를 사용하여 나무를 구현했습니다. 꽤 쉽게 할 수 있으며 꽤 큰 데이터 세트로 저에게 효과적입니다. 아래 샘플을 게시했으며 Google 코드에서 더 많은 것을 볼 수 있습니다.
중첩 된 dicts를 사용하여 나무를 구현했습니다. 꽤 쉽게 할 수 있으며 꽤 큰 데이터 세트로 저에게 효과적입니다. 아래 샘플을 게시했으며 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)
-
==============================
10.
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
사전으로 작동하지만 원하는만큼 중첩 된 dicts를 제공합니다. 다음을 시도하십시오.
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'] = '*'
실제로 나무처럼 작동하는 중첩 된 dict을 제공 할 것입니다.
{'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
이 방법으로 원하는대로 각 사전 수준을 편집 / 추가 / 제거 할 수 있습니다. traversal에 대한 모든 dict 메소드는 여전히 적용됩니다.
-
==============================
11.내 사이트에 파이썬 [3] 트리 구현을 게시했습니다 : http://www.quesucede.com/page/show/id/python_3_tree_implementation.
내 사이트에 파이썬 [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)
-
==============================
12.어떤 작업이 필요합니까? dict 또는 bisect 모듈을 사용하는 목록을 사용하여 파이썬에서 좋은 해결책이되는 경우가 많습니다.
어떤 작업이 필요합니까? dict 또는 bisect 모듈을 사용하는 목록을 사용하여 파이썬에서 좋은 해결책이되는 경우가 많습니다.
PyPI에는 많은 트리 구현이 있으며 많은 트리 유형은 순수 Python에서 구현하기가 거의 쉽지 않다. 그러나 이것은 거의 필요하지 않습니다.
-
==============================
13.브루노 (Bruno)의 대답을 바탕으로 느슨하게 다른 트리 구현 :
브루노 (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
그리고 그것을 사용하는 방법의 예 :
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)
출력해야하는 항목 :
Root node / / \ Child node 0 Child node 1 Child node 2 | / \ Grandchild 1.0 Grandchild 2.0 Grandchild 2.1
-
==============================
14.
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)
from https://stackoverflow.com/questions/2358045/how-can-i-implement-a-tree-in-python-are-there-any-built-in-data-structures-in by cc-by-sa and MIT license
'PYTHON' 카테고리의 다른 글
[PYTHON] Python : 사전을 사용하여 목록의 항목 계산 [duplicate] (0) | 2018.10.06 |
---|---|
[PYTHON] 파이썬 클래스 장식 자 (0) | 2018.10.06 |
[PYTHON] 어떻게 장고 DateTimeField의 날짜를 필터링 할 수 있습니까? (0) | 2018.10.06 |
[PYTHON] 파이썬에서 전체 파일 읽기 (0) | 2018.10.06 |
[PYTHON] matplotlib 줄거리에서 내 xlabel이 왜 끊깁니까? (0) | 2018.10.06 |