좋은 파이썬 트리 데이터 구조를 찾고 있습니다.


92

좋은 트리 데이터 구조 클래스를 찾고 있습니다. 나는 이 패키지 를 보았지만, 나는 파이썬 (프로그래밍이 아님)을 비교적 처음 접했기 때문에 더 나은 것이 있는지 모르겠습니다.

여기에있는 Pythonistas의 의견을 듣고 싶습니다. 정기적으로 사용하고 추천하는 좋아하는 트리 스크립트가 있습니까?

[편집하다]

명확히하기 위해, '트리'는 단순하게 정렬되지 않은 트리를 의미합니다 (음, 그것은 약간의 재귀 적 정의입니다. 트리가 필요한 이유 (예 : 유스 케이스). 플랫 파일에서 트리 데이터를 읽고 데이터에서 트리를 만들고 트리의 모든 노드를 트래버스해야합니다.



1
: 그 동안, 간단하고, 가볍고 확장 가능한 트리 데이터 구조가 anytree.readthedocs.io/en/latest
c0fec0de

답변:


38

직접 굴려보세요. 예를 들어, 트리를 목록 목록으로 모델링하십시오. 사람들이 더 나은 추천을 제공하기 전에 구체적인 요구 사항을 자세히 설명해야합니다.

HelloGoodbye의 질문에 대한 응답으로 트리를 반복하는 샘플 코드입니다.

def walk(node):
    """ iterate tree in pre-order depth-first search order """
    yield node
    for child in node.children:
        for n in walk(child):
            yield n

한 가지 캐치는이 재귀 적 구현이 O (n log n)이라는 것입니다. 내가 처리해야하는 모든 나무에 대해 잘 작동합니다. 아마도 파이썬 3의 하위 생성기가 도움이 될 것입니다.


그런 트리의 모든 요소를 ​​'파이썬'방식으로 어떻게 반복합니까?
HelloGoodbye 2014 년

일반적으로 DFS 또는 BFS를 사용하여 트리를 반복합니다. ... : 나는 보통 데프 도보 같은 DFS (나무)를 사용하여 생성기 구현
와이 깨갱 퉁

1
DFS와 BFS는 무엇입니까? 이 두문자어는 저에게 새로운 것입니다.
HelloGoodbye 2014 년

1
DFS에 대한 샘플 코드를 추가했습니다.
Wai Yip Tung

1
깊이 우선 검색은 노드의 자식이 형제보다 먼저 방문됨을 의미합니다. 따라서`[A, [B, [C, D]], [E, [F, G]]]`가있는 경우 E 이전에 B를 방문한다고 가정하면 E 이전에 C와 D도 방문합니다. Breadth- B와 E는 모두 C, D, F, 또는 G.의 전에 방문 할 것이다, 그래서 동일한 수준에서 모든 노드 첫 번째 검색 수단은 자녀의 전에 방문하는
마크 리드

76

다음과 같이 dicts의 멋진 트리를 만들 수 있습니다.

import collections

def Tree():
    return collections.defaultdict(Tree)

정확히 원하는 것이 아닐 수도 있지만 매우 유용합니다! 값은 리프 노드에만 저장됩니다. 작동 방식의 예는 다음과 같습니다.

>>> t = Tree()
>>> t
defaultdict(<function tree at 0x2142f50>, {})
>>> t[1] = "value"
>>> t[2][2] = "another value"
>>> t
defaultdict(<function tree at 0x2142f50>, {1: 'value', 2: defaultdict(<function tree at 0x2142f50>, {2: 'another value'})}) 

자세한 내용 은 요점을 참조하십시오 .


1
와우, defaultdict를 사용하는 것은 훌륭한 아이디어입니다!
laike9m

훌륭하고 나는 세터를 제외하고는 항상 try를 사용합니다.
Jimmy Kane

5
한 가지 단점은 트리 조작과 관련된 메서드를 추가하는 것이 매우 까다 롭다는 것입니다. 이 위키에 있으며 autovivification 전화 : en.wikipedia.org/wiki/Autovivification#Python
denfromufa

41

완료되지 않은 Brett Alistair Kromkamp가 작성한 모듈을 찾았습니다. 나는 그것을 끝내고 github에서 공개하고 이름을 treelib(original pyTree) :

https://github.com/caesar0301/treelib

도움이 되길 바랍니다 ....


5
라이선스는 GPL, 어떤 유감입니다
denfromufa

12
이 라이센스는 라이센스가 무엇을 의미하는지 알지 못했을 때 부여되었습니다. 간단하지만 유용한 모듈이라는 것을 알고 있습니다. 버전 1.3.0부터 Apache 라이선스로 재배포합니다. 이제 원본 저작권을 선언하여 필요한 곳에서 사용할 수 있습니다.
caesar0301 2014

9

바탕 defaultdict를 사용하여 한 줄 나무 위의 대답은 , 당신은 클래스를 만들 수 있습니다. 이렇게하면 생성자에서 기본값을 설정하고 다른 방법으로 빌드 할 수 있습니다.

class Tree(defaultdict):
    def __call__(self):
        return Tree(self)

    def __init__(self, parent):
        self.parent = parent
        self.default_factory = self

이 예제에서는 각 노드가 트리에서 부모를 참조 할 수 있도록 역 참조를 만들 수 있습니다.

>>> t = Tree(None)
>>> t[0][1][2] = 3
>>> t
defaultdict(defaultdict(..., {...}), {0: defaultdict(defaultdict(..., {...}), {1: defaultdict(defaultdict(..., {...}), {2: 3})})})
>>> t[0][1].parent
defaultdict(defaultdict(..., {...}), {1: defaultdict(defaultdict(..., {...}), {2: 3})})
>>> t2 = t[0][1]
>>> t2
defaultdict(defaultdict(..., {...}), {2: 3})
>>> t2[2]
3

다음으로, Tree 클래스에서 __setattr__을 재정 의하여 부모를 재 할당 할 때 부모에서 자식으로 제거하도록 할 수도 있습니다. 이 패턴으로 멋진 물건이 많이 있습니다.


위의 예에서 t [0] [1] [2]에 대한 부모가 끊어졌습니다. AttributeError : 'int'개체에 'parent'속성이 없습니다
MatthieuBizien

@oao 이것은 깨지지 않았습니다. t [0] [1] [2] = 3을 지정합니다. 따라서 t [0] [1] [2]는 defaultdict 유형이 아니라 Number 유형입니다 (defaultdict는 누락 된 요소). defaultdict로 사용하려면 할당없이 t [0] [1] [2]를 사용해야합니다.
Sandy Chapman

7

정렬 된 아이들이있는 나무의 경우, 보통 다음과 같은 일을합니다 (좀 덜 일반적이고 제가하는 일에 맞게 조정 됨).

class TreeNode(list):

    def __init__(self, iterable=(), **attributes):
        self.attr = attributes
        list.__init__(self, iterable)

    def __repr__(self):
        return '%s(%s, %r)' % (type(self).__name__, list.__repr__(self),
            self.attr)

당신은 dict또는 using 과 비슷한 것을 할 수 DictMixin있거나 키로 정렬되지 않은 아이들을 원할 경우 더 현대적인 자손입니다.


7

networkx 라이브러리를 사용하여 비순환 방향 그래프를 기반으로 자체 트리 래퍼를 작성하는 것이 좋습니다.


5

파이썬에서 사용하기 쉬운 또 다른 트리 구현은 pyTree입니다 : https://github.com/caesar0301/pyTree

pyTree는 또한 트리를 시각화하는 가능성을 제공합니다.

Harry[harry]
|___ Jane[jane]
|    |___ Diane[diane]
|         |___ George[george]
|              |___ Jill[jill]
|         |___ Mary[mary]
|    |___ Mark[mark]
|___ Bill[bill]

2
렌더링이 끔찍 했음에도 불구하고 트리를 시각화하는 데 도움이됩니다.
HelloGoodbye 2014 년


4

여기 제가 작업하고있는 것이 있습니다.

class Tree:
    def __init__(self, value, *children):
        '''Singly linked tree, children do not know who their parent is.
        '''
        self.value = value
        self.children = tuple(children)

    @property
    def arguments(self):
        return (self.value,) + self.children

    def __eq__(self, tree):
        return self.arguments == tree.arguments

    def __repr__(self):
        argumentStr = ', '.join(map(repr, self.arguments))
        return '%s(%s)' % (self.__class__.__name__, argumentStr)

다음과 같이 사용하십시오 (예시 값으로 사용 된 숫자). t = Tree(1, Tree(2, Tree(4)), Tree(3, Tree(5)))


3

겠습니까 한데, btree의 도움? Zope 개체 데이터베이스 코드의 일부입니다. 전체 ZODB 패키지를 다운로드하는 것은 약간 과잉이지만 BTrees 모듈이 적어도 어느 정도 분리 될 수 있기를 바랍니다.


2

더 발전된 데이터 구조의 문제에 대한 저의 경험을 통해 여기서 할 수있는 가장 중요한 일은 데이터 구조로서의 트레스의 일반적인 개념에 대한 좋은 지식을 얻는 것이라고 생각합니다. 개념의 기본 메커니즘을 이해하면 문제에 맞는 솔루션을 구현하기가 매우 쉽습니다. 개념을 설명하는 좋은 출처가 많이 있습니다. 이 특정 문제에 대해 몇 년 전에 나를 "구해준"것은 "컴퓨터 프로그래밍 기술"의 섹션 2.3이었습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.