0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

階層構造をツリーに変換するコード

Posted at

経緯

・以下のような階層構造ツリーを作りたい。

入力:
[0,1,2,2,2,3,2,2,3,2,3,4,4,5,5,4,4,5,4,4,1,1,1,2,1,1,1]

出力:
┬────
├┬───
│├───
│├───
│├┬──
││└──
│├───
│├┬──
││└──
│└┬──
│ └┬─
│  ├─
│  ├┬
│  │├
│  │└
│  ├─
│  ├┬
│  │└
│  ├─
│  └─
├────
├────
├┬───
│└───
├────
├────
└────

・階層構造ツリーを作成する関連で調べても、ディレクトリ風のテキストを作るものしか出てこない
⇒自分で作りました。

結論

とりあえずpythonで記載

code1.py
def generate_tree(depths):
    """
    depths: list of non-negative整数。最初の要素は0で、それ以降に0は出てこないものとする。
    戻り値: 各行を表す罫線ツリーの文字列リスト。
    """
    # 入力チェック
    if len(depths) < 2:
        raise ValueError("入力は2行以上必要です")
    if depths[0] != 0 or any(d == 0 for d in depths[1:]):
        raise ValueError("1行目のみ0、それ以降に0は許されません")
    
    max_depth = max(depths)
    V, H, S = '', '', ' '   # 縦線, 横線, 全角スペース
    T, TEE, ELB = '', '', ''
    n = len(depths)
    lines = []
    
    for i, d in enumerate(depths):
        # 子ノード判定
        has_child = (i+1 < n and depths[i+1] > d)
        
        # 兄弟ノード判定
        has_sibling = False
        for j in range(i+1, n):
            if depths[j] < d:
                break
            if depths[j] == d:
                has_sibling = True
                break
        
        row = []
        for pos in range(max_depth):
            if pos < d-1:
                # ── 祖先レベルの縦線判定 ──
                # 後続行を順に見て、
                #   ・depths[j] < pos+1 → その祖先ブランチは終了 → 縦線なし
                #   ・depths[j] > pos → まだそのブランチに子孫あり → 縦線あり
                #   ・depths[j] == pos+1 → 同じレベルの子や孫 → 縦線あり
                # のいずれかで判定を打ち切る
                draw_v = False
                for j in range(i+1, n):
                    if depths[j] < pos+1:
                        # 祖先レベル pos はもう続かない
                        break
                    elif depths[j] == pos+1:
                        # depths[j] >= pos の間は縦線を引く
                        draw_v = True
                        break
                row.append(V if draw_v else S)

            elif pos == d-1:
                # 親からの分岐 ├ または └
                row.append(TEE if has_sibling else ELB)

            elif pos == d:
                # 自分自身の分岐 ┬(子あり)/─(子なし)
                row.append(T if has_child else H)

            else:
                # それ以降は横線で埋める
                row.append(H)
        
        lines.append(''.join(row))
    
    return lines


if __name__ == "__main__":
    # テスト用サンプル
    sample = [0,1,2,2,2,3,2,2,3,2,3,4,4,5,5,4,4,5,4,4,1,1,1,2,1,1,1]
    for line in generate_tree(sample):
        print(line)

関数として記載しています。
これを適宜、自分のツールに組み込みましょう

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?