良いPython Treeデータ構造を探しています[終了]


92

優れたTreeデータ構造クラスを探しています。私はこのパッケージに出くわしましたが、私は比較的Python(プログラミングではない)に慣れていないので、他にもっと良いものがあるかどうかわかりません。

ここで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

1つの問題は、この再帰的な実装がO(n log n)であることです。それは私が対処しなければならないすべての木のためにうまく働きます。多分Python 3のサブジェネレーターが役立つでしょう。


そのようなツリーのすべての要素を「pythonic」の方法でどのようにループしますか?
HelloGoodbye 2014年

通常、DFSまたはBFSを使用してツリーを反復処理します。私は通常、def walk(tree)のようなDFSを使用してジェネレーターを実装します:...
Wai Yip Tung

1
DFSおよびBFSとは何ですか?これらの頭字語は私にとって新しいものです。
HelloGoodbye 2014年

1
DFSのサンプルコードを追加しました。
Wai Yip Tung

1
深さ優先検索は、ノードの子がその兄弟の前に訪問されることを意味します。したがって、 `[A、[B、[C、D]]、[E、[F、G]]]`がある場合、Eの前にBにアクセスすると仮定すると、Eの前にCとDにもアクセスします。 B及びEの両方がC、D、F、またはGのいずれかの前に訪問されるように同じレベルのすべてのノードは、その子のいずれかの前に訪問された第1の検索手段
マーク・リード

76

次のように、dictsの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 2013年

素晴らしいです。セッター以外では常にtryを使用しています。
ジミー・ケイン

5
1つの欠点は、ツリー操作に関連するメソッドを追加するのが非常に難しいことです。また、これはウィキにあり、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 14

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またはと同等の処理を行うか、より新しいDictMixin子孫を使用できます。



5

Pythonでのツリーのもう1つの優れた使いやすい実装は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 Object Databaseコードの一部です。ZODBパッケージ全体をダウンロードすることは少々やり過ぎですが、BTreesモジュールが少なくともある程度分離可能であることを願っています。


2

より高度なデータ構造に関する問題についての私自身の経験から、ここで実行できる最も重要なことは、データ構造としてのトレスの一般的な概念についての十分な知識を得ることだと思います。概念の背後にある基本的なメカニズムを理解していれば、問題に合ったソリューションを簡単に実装できます。コンセプトを説明している良い情報源はたくさんあります。この特定の問題について何年か前に私が「救った」のは、「コンピュータプログラミングの芸術」のセクション2.3でした。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.