-
-
Save p--q/bf5456915001c63cb298 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
class Tree: # これのインスタンスが二分木のノードとなる。 | |
def __init__(self, label, left=None, right=None): # インスタンス化のときの第一引数をノードの値に、第二引数を左の枝につながるノードに、第3引数を右の枝につながるノードにする。 | |
self.label = label # ノードの値を設定。 | |
self.left = left # 左の枝につながるノードを設定。 | |
self.right = right # 右の枝につながるノードを設定。 | |
def __repr__(self, level=0, indent=" "): # repr(このクラスのインスタンス)で呼び出されたときに文字列を返す特殊メソッド。repr(ノード)でそのノードから葉まで出力する。levelは木の階層(根を0階層とする)、indentは出力するときのインデント。 | |
stack = [self, level] # 初期値のノードインスタンスとその階層をスタックに入れる。 | |
s = "" # 結果を入れる文字列。 | |
while stack: # スタックがあるあいだ続行。 | |
node, level = stack[-2:] # スタックからノードインスタンスと階層を得る。 | |
if node.left: # 左の枝があるとき。 | |
s += "\n" + level*indent + node.label # ノードの値をその階層で出力。 | |
stack.extend([node.left, level + 1]) # 左の枝のノードインスタンスとその階層をスタックに追加する。 | |
node.left = None # 使用後の左の枝を消去。 | |
elif node.right: # 右の枝があるとき。 | |
del stack[-2:] # もうこのノードインスタンスは使わないのでスタックから削除。 | |
stack.extend([node.right, level + 1]) # 右の枝のノードインスタンスとその階層をスタックに追加する。 | |
else: # 左右の枝がないとき。 | |
s += "\n" +level*indent + node.label # ノードの値をその階層で出力。 | |
del stack[-2:] # ノードインスタンスをスタックから消去。 | |
return s | |
def tree(lst): # 引数のリストから二分木を作成する関数。 | |
node = list() # ノードインスタンスを収納するスタック。 | |
node_level = list() # ノードインスタンスの二分木での階層を保存するスタック。 | |
if len(lst) > 3: | |
i = len(lst) // 2 # ノードの値にする要素番号を取得。 | |
stack = [lst[i], lst[i+1:], lst[:i]] # スタックに初期値を入力。初期値; ノードの値、左のノードとなる値のリスト、右のノードとなる値のリスト。 | |
level = [0, 1, 1] # stackの要素のリスとの二分木での階層を保存するスタック。 | |
else: # リストの要素が3個以下のときはまとめて処理する。 | |
stack = [lst] | |
level = [0] | |
while stack: # ノードの値となる要素をもったリストがある間。 | |
lst = stack.pop() # リストを取り出す。 | |
if len(lst) > 3: # リストの要素が3以上あるとき。 | |
i = len(lst) // 2 # ノードの値にする要素番号を取得。 | |
stack.extend([lst[i], lst[i+1:], lst[:i]]) # ノードの値、左のノードとなる値のリスト、右のノードとなる値のリスト,をスタックに新たに追加。 | |
n = level[-1]+1 # 階層を1つ加えるて、階層スタックに追加する。 | |
level.extend([n, n]) | |
elif len(lst) == 1: # リストの要素が一つだけのとき。 | |
if len(node_level) > 1 and node_level[-1] == node_level[-2]: # ノードインスタンスが複数あり、かつ階層が同一のとき。 | |
left = node.pop() | |
right = node.pop() | |
node.append(Tree(lst[0], right, left)) # リストの要素を値とするノードインスタンスを生成して、ノードインスタンス用のスタックに追加。 | |
node_level.pop() # ノードを二つ消費したのでノードの階層のスタックの要素を一つ破棄。 | |
node_level[-1] -= 1 # 新たに生成したノードインスタンスの階層を設定。ノードを結合したノードの階層は一つ根に近づく。 | |
level.pop() # リストのスタックも要素を一つ消費したので階層のスタックを一つ破棄する。 | |
else: # ノードインスタンスがないときは枝のないノードにする。 | |
node.append(Tree(lst[0])) | |
node_level.append(level.pop()) # リストの階層からノードの階層を取得。 | |
elif lst: # リストの要素が2個か3個のときはすべてノードにしてしまう。 | |
i = len(lst) // 2 # ノードの値にする要素番号を取得。 | |
node.append(Tree(lst[i], Tree(lst[:i]), Tree(lst[i+1:]))) # i番目の要素をノードの値、i-1番目の要素を右のノードの値、i+1番目の要素の値を左のノードの値にする。左右のノードより深い階層のノードは存在しない。 | |
node_level.append(level.pop()) # リストの階層からノードの階層を取得。 | |
return node[0] # 最後にスタックに残ったノードが根となるのでそれを返す。 | |
t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ") # 引数のリストから二分木を生成してその根をtに取得。 | |
print(repr(t)) # 根tについてpreorder(行きかけ順)に出力。 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment