package main
import (
"fmt"
)
type IntTree struct {
val int
left, right *IntTree
}
// valをitに挿入する
func (it *IntTree) Insert(val int) *IntTree {
if it == nil {
return &IntTree{val: val}
}
if val < it.val {
it.left = it.left.Insert(val)
} else if val > it.val {
it.right = it.right.Insert(val)
}
return it
}
// valがitに含まれるかをチェックし論理値を返す
func (it *IntTree) Contains(val int) bool {
switch {
case it == nil:
return false
case val < it.val:
return it.left.Contains(val)
case val > it.val:
return it.right.Contains(val)
default:
return true
}
}
func main() {
var it *IntTree
it = it.Insert(5)
it = it.Insert(3)
it = it.Insert(10)
it = it.Insert(2)
fmt.Println(it.Contains(2)) // true
fmt.Println(it.Contains(12)) // false
}
type IntTree struct { //liststart1
val int
left, right *IntTree
}
-
IntTree
という構造体を定義します。この構造体は、整数の値(val
)と、左と右の子ノード(left
とright
)を持っています。これにより、二分探索木(BST)を表現します。
// valをitに挿入する
func (it *IntTree) Insert(val int) *IntTree {
-
Insert
メソッドを定義します。このメソッドは、整数val
を木に挿入するためのものです。it
はIntTree
のポインタです。
if it == nil {
return &IntTree{val: val}
}
-
it
がnil
の場合、新しいIntTree
のインスタンスを作成し、val
をその値に設定して返します。
if val < it.val {
it.left = it.left.Insert(val)
} else if val > it.val {
it.right = it.right.Insert(val)
}
-
val
が現在のノードの値より小さい場合、左の子ノードに対してInsert
を再帰的に呼び出します。逆に、大きい場合は右の子ノードに対して呼び出します。
return it
}
- 最後に、現在のノード(
it
)を返します。これにより、木全体の構造が保持されます。
// valがitに含まれるかをチェックし論理値を返す
func (it *IntTree) Contains(val int) bool {
-
Contains
メソッドを定義します。このメソッドは、整数val
が木に存在するかどうかをチェックします。
switch {
case it == nil:
return false
-
it
がnil
の場合、木に値は含まれないのでfalse
を返します。
case val < it.val:
return it.left.Contains(val)
-
val
が現在のノードの値より小さい場合、左の子ノードに対してContains
を再帰的に呼び出します。
case val > it.val:
return it.right.Contains(val)
-
val
が現在のノードの値より大きい場合、右の子ノードに対してContains
を再帰的に呼び出します。
default:
return true
}
-
val
が現在のノードの値と等しい場合、木に値が含まれているのでtrue
を返します。
func main() { //liststart2
-
main
関数を定義します。プログラムのエントリーポイントです。
var it *IntTree
-
IntTree
のポインタit
を宣言しますが、まだ初期化はされていません。
it = it.Insert(5)
-
5
を木に挿入し、その結果をit
に再代入します。最初のノードが作成されます。
it = it.Insert(3)
-
3
を木に挿入します。3
は5
より小さいので、左の子ノードとして追加されます。
it = it.Insert(10)
-
10
を木に挿入します。10
は5
より大きいため、右の子ノードとして追加されます。
it = it.Insert(2)
-
2
を木に挿入します。2
は5
より小さく、さらに3
よりも小さいので、3
の左に追加されます。
fmt.Println(it.Contains(2)) // true
-
2
が木に含まれているかをチェックし、結果を出力します。true
が出力されます。
fmt.Println(it.Contains(12)) // false
IntTree
がどのように構築されるか
初期状態
最初は、it
はnil
です。
var it *IntTree
it = it.Insert(5)
-
it
がnil
なので、Insert
メソッドは新しいIntTree
インスタンスを作成します。 -
val
は5
です。 - 新しいノードが作成され、
5
がその値になります。 -
it
はこの新しいノードを指すようになります。
5
/ \
nil nil
it = it.Insert(3)
- 現在のノードは
5
です。 -
3 < 5
なので、左の子ノードに挿入します。 - 左の子ノードは
nil
なので、Insert
メソッドは新しいノードを作成します。 -
val
は3
です。 - 新しいノードが作成され、
3
がその値になります。
5
/ \
3 nil
/ \
nil nil
it = it.Insert(10)
- 現在のノードは
5
です。 -
10 > 5
なので、右の子ノードに挿入します。 - 右の子ノードは
nil
なので、Insert
メソッドは新しいノードを作成します。 -
val
は10
です。 - 新しいノードが作成され、
10
がその値になります。
5
/ \
3 10
/ \ / \
nil nil nil
it = it.Insert(2)
- 現在のノードは
5
です。 -
2 < 5
なので、左の子ノード(3
)に進みます。 - 現在のノードは
3
です。 -
2 < 3
なので、左の子ノードに挿入します。 - 左の子ノードは
nil
なので、Insert
メソッドは新しいノードを作成します。 -
val
は2
です。 - 新しいノードが作成され、
2
がその値になります。
5
/ \
3 10
/ \ / \
2 nil nil
/ \
nil nil
最終的な木の構造
全ての挿入操作が完了した後、最終的な二分探索木の構造は次のようになります。
5
/ \
3 10
/ \
2 nil
/ \
nil nil
結果
-
5
がルートノード。 -
3
が5
の左の子ノード。 -
10
が5
の右の子ノード。 -
2
が3
の左の子ノード。