Skip to content

Instantly share code, notes, and snippets.

@p--q

p--q/python18.py Secret

Last active August 29, 2015 14:03
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/248b8a27f40ebebb9414 to your computer and use it in GitHub Desktop.
Save p--q/248b8a27f40ebebb9414 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, level=0, indent=" "): # repr(このクラスのインスタンス)で呼び出されたときに文字列を返す特殊メソッド。repr(ノード)でそのノードから葉まで出力する。levelは木の階層(根を0階層とする)、indentは出力するときのインデント。
s = level*indent + repr(self.label) # ノードの値を階層に応じたインデントをつけて出力する。sが出力する文字列になる。
if self.left: # 左の枝につながるノードがあるとき。
s = s + "\n" + self.left.__repr__(level+1, indent) # 左の枝につながるノードについて階層を一つ加えて出力する。
if self.right: # 右の枝につながるノードがあるとき。
s = s + "\n" + self.right.__repr__(level+1, indent) # 右の枝につながるノードについて階層を一つ加えて出力する。
return s # repr(ノード)のノードについてpreorder(行きかけ順)(出力、左の枝、右の枝の順に処理したから)にそのノードから葉まで出力することになる。
def tree(lst): # 引数のリストから二分木を作成する関数。
node = list() # ノードインスタンスを収納するスタック。
node_level = [] # ノードインスタンスの二分木での階層を保存するスタック。
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