Skip to content

Instantly share code, notes, and snippets.

@p--q

p--q/python22.py Secret

Last active August 29, 2015 14:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save p--q/06702ff975e3adcd7a5f to your computer and use it in GitHub Desktop.
Save p--q/06702ff975e3adcd7a5f to your computer and use it in GitHub Desktop.
# -*- 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): # repr(このクラスのインスタンス)で呼び出されたときに文字列を返す特殊メソッド。デバッグ画面でもこの戻り値が表示されるのでデバッグ用。
return self.label # ノードの値のみ出力する。
def tree_repr(t, indent=" "): # 根tの二分木を枝付きで出力。
stack = [t] # ノードインスタンスをいれるスタックにまず根tを入れる。inorder(通りがけ順)に取得する。
lst_level = [0] # stackのノードインスタンスに対応する階層を入れるリスト。
b = 0 # 枝の状態を保持する二進数。1桁目が0階層目。
while stack: # ノードインスタンスがある間実行。
node = stack.pop() # ノードインスタンスを取得。
level = lst_level.pop() # ノードインスタンスの階層を取得。
branch = "" # 枝を入れる変数を初期化。
while node.left: # 左の枝につながるノードがあるとき。
n_node = node.left # 次のノードとして左の枝につながるノードを取得。
node.left = None # 使用したノードは消す。
stack.append(node) # 左の枝につながるノードを消した状態でスタックに取得。
lst_level.append(level) # スタックに取得したノードに対応する階層を取得。
node = n_node # 次のノードを設定。
level += 1 # 子ノードなので階層を一つ増やす。
if level > 1: # 2階層以上のとき。
for i in range(level - 1): # 2つ下の階層まで縦枝があるかをみる。
if b & (2 ** i):
branch += "│ "
else:
branch += indent
if level > 0: # 1階層以上のとき。
if node.label: # ノードの値があるとき。
if level - 1 in lst_level: # スタックに下の階層のノードがあるとき。
branch += "┌─"
b |= 2 ** (level - 1) # ノードの一つ下の階層の縦枝のフラグを立てる。
else: # スタックの下の階層のノードがないとき。
branch += "└─"
b -= b & 2 ** (level - 1) # ノードの一つ下の階層の縦枝のフラグを消す。
print(branch + node.label) # ノードの値とともに枝を出力。
b &= 2 ** level - 1 # ノードより上の階層のフラグをすべて消す。
b |= 2 ** level # このノードの階層のフラグを立てる。
if node.right: # 右の枝につながるノードをあるとき。
stack.append(node.right) # スタックに加える。
lst_level.append(level + 1)
def tree(lst): # 引数のリストから二分木を作成する関数。
node = list() # [ノードインスタンス, 階層]のリストを要素とするリスト。
stack = [[lst, 0]] # [ノードの値のリスト, 階層]のリストを要素とするスタック。
while stack: # ノードの値となる要素をもったリストがある間。
lst, level = stack.pop() # リストと階層を取り出す。
if len(lst) > 3: # リストの要素が3以上あるとき。
i = len(lst) // 2 # ノードの値にする要素番号を取得。
stack.extend([[lst[i], level], [lst[i+1:], level + 1], [lst[:i], level + 1]]) # ノードの値、左のノードとなる値のリスト、右のノードとなる値のリスト,をスタックに新たに追加。
elif len(lst) == 1: # リストの要素が一つだけのとき。
if len(node) > 1 and node[-2][1] == node[-1][1]: # ノードインスタンスが複数あり、かつ階層が同一のとき。
left = node.pop()[0] # 左の枝につながるノードを得る。
right = node.pop()[0] # 右の枝につながるノードを得る。
node.append([Tree(lst[0], right, left), level]) # リストの要素を値とするノードインスタンスを生成して、ノードインスタンス用のスタックに追加。
else: # ノードインスタンスがないときは枝のないノードにする。
node.append([Tree(lst[0]), level])
elif lst: # リストの要素が2個か3個のときはすべてノードにしてしまう。
i = len(lst) // 2 # ノードの値にする要素番号を取得。
node.append([Tree(lst[i], Tree(lst[:i]), Tree(lst[i+1:])), level]) # i番目の要素をノードの値、i-1番目の要素を右のノードの値、i+1番目の要素の値を左のノードの値にする。左右のノードより深い階層のノードは存在しない。
return node[0][0] # 最後にスタックに残ったノードが根となるのでそれを返す。
t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ") # 引数のリストから二分木を生成してその根をtに取得。
tree_repr(t) # 根tについて枝付きで出力。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment