マイケルの答えは、おそらくあなたが問題に取り組むことになっていた方法を説明していますが、彼はあなたの現在の試みの何が悪いのかを説明していませんでした。私が理解しているように、あなたの戦略は、各ノードを調べ、再帰を使用してすべてのノードを見つけることで、進行中の最小値を追跡することでした。すべてのノードを調べたら、結果がツリー全体の最小値であることがわかります。これは完全に有効なアプローチであり、引数が期待どおりに機能しないことを除いては機能します。
Pythonは、参照ではなく値で引数を渡します。「min_t=root.key」を使用してmin_tに値を割り当てると、関数内でのみ有効になります。関数の呼び出し元には、新しい値は表示されません。
これは、いくつかの簡単なコードでテストできます。
def add_one_to(x):
x = x + 1
print "add_one_to", x
x = 2
add_one_to(x)
print x
コードを実行すると、xが関数内でインクリメントされたが、トップレベルではインクリメントされなかったことがわかります。
これは、関数がそれ自体を呼び出すときにも当てはまります。各呼び出しには独自のローカル変数のセットがあり、関数内でローカル変数に割り当てても、それを呼び出したインスタンスには影響しません。
一部の言語では、参照によって引数を渡すことができることに注意してください。参照によって引数を渡す場合、関数内でその引数を割り当てると、呼び出し元にも影響します。Pythonがそれらの言語の1つである場合、min_tを参照引数にすることができ、関数は正しく機能します。
Pythonは参照引数を直接サポートしていませんが、参照引数は、呼び出されたときに関数に入り、関数が完了したときに呼び出し元に返される値と考えることもできます。これらの両方を別々に行うことができます。値を呼び出し元に戻すには、その値を返します。その後、呼び出し元はその関数をローカルに割り当てることができ、基本的に参照によって引数を渡しました。
上記の例にそれを適用する方法は次のとおりです。
def add_one_to(x):
x = x + 1
print "add_one_to", x
return x
x = 2
x = add_one_to(x)
print x
戻り値と割り当てを追加するだけで、正常に機能します。
これを元の関数に適用することもできます。
def min(root, min_t): # min_t is the initially the value of root
if not root:
return min_t
if root.key < min_t:
min_t = root.key
min_t = min(root.left, min_t)
min_t = min(root.right, min_t)
return min_t
私がしたのは、min()を呼び出すたびに「min_t =」を追加し、returnステートメントを変更して最後にmin_tを返すことだけでした。(とにかくmin_tを返すつもりだったと思います。minは関数の名前なので、あまり意味がありません。)バージョンは機能すると思います。
編集:これにもかかわらず、min_tree関数が機能する理由は、nがリストであり、リストが可変オブジェクトであるためです。上記の「値」について話していたとき、私が本当に意味したのは「オブジェクト」でした。Pythonの各変数名は、特定のオブジェクトにマップされます。このようなコードがある場合:
def replace_list(x):
x = [1, 2, 3]
x = [2]
replace_list(x)
print x
結果は[2]です。したがって、「x =」を使用してxに新しい値を割り当てると、呼び出し元にはその値が表示されません。ただし、これを行う場合:
def replace_list(x):
x.append(1)
x = [2]
replace_list(x)
print x
結果は[2、1]です。これは、xの値を変更していないためです。xはまだ同じリストを指しています。ただし、そのリストには追加の値が含まれるようになりました。残念ながら、「+=」演算子はこの点で混乱しています。「x+=y」は「x=x + y」と同じだと思うかもしれませんが、Pythonでは常にそうであるとは限りません。「x」が「+=」を具体的にサポートする一種のオブジェクトである場合、その操作はその場でオブジェクトを変更します。それ以外の場合は、「x =x+1」と同じになります。リストは「+=」の処理方法を知っているため、リストで+ =を使用するとその場で変更されますが、数値で使用しても変更されません。
関数呼び出しを行わずに、これを実際にテストできます。
x = [1, 2]
y = x
y += [3]
print x # [1, 2, 3]
print y # [1, 2, 3]
print x is y # True, x and y are the same object, which was modified in place
x = [1, 2]
y = x
y = y + [3]
print x # [1, 2]
print y # [1, 2, 3]
print x is y # False, y is a new object equal to x + [3]
x = 1
y = x
y += 2
print x # 1
print y # 3
print x is y # False, y is a new object equal to x + 2