0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Go言語(Golang)におけるレシーバがnilを受け取ることを利用した二本木の実装

Last updated at Posted at 2024-10-14
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)と、左と右の子ノード(leftright)を持っています。これにより、二分探索木(BST)を表現します。
// valをitに挿入する
func (it *IntTree) Insert(val int) *IntTree {
  • Insertメソッドを定義します。このメソッドは、整数valを木に挿入するためのものです。itIntTreeのポインタです。
	if it == nil {
		return &IntTree{val: val}
	}
  • itnilの場合、新しい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
  • itnilの場合、木に値は含まれないので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を木に挿入します。35より小さいので、左の子ノードとして追加されます。
	it = it.Insert(10)
  • 10を木に挿入します。105より大きいため、右の子ノードとして追加されます。
	it = it.Insert(2)
  • 2を木に挿入します。25より小さく、さらに3よりも小さいので、3の左に追加されます。
	fmt.Println(it.Contains(2))  // true
  • 2が木に含まれているかをチェックし、結果を出力します。trueが出力されます。
	fmt.Println(it.Contains(12)) // false

IntTreeがどのように構築されるか

初期状態

最初は、itnilです。

var it *IntTree

it = it.Insert(5)

  • itnilなので、Insertメソッドは新しいIntTreeインスタンスを作成します。
  • val5です。
  • 新しいノードが作成され、5がその値になります。
  • itはこの新しいノードを指すようになります。
   5
  / \
nil nil

it = it.Insert(3)

  • 現在のノードは5です。
  • 3 < 5なので、左の子ノードに挿入します。
  • 左の子ノードはnilなので、Insertメソッドは新しいノードを作成します。
  • val3です。
  • 新しいノードが作成され、3がその値になります。
   5
  / \
  3 nil
 / \
nil nil

it = it.Insert(10)

  • 現在のノードは5です。
  • 10 > 5なので、右の子ノードに挿入します。
  • 右の子ノードはnilなので、Insertメソッドは新しいノードを作成します。
  • val10です。
  • 新しいノードが作成され、10がその値になります。
   5
  / \
  3  10
 / \  / \
nil nil nil

it = it.Insert(2)

  • 現在のノードは5です。
  • 2 < 5なので、左の子ノード(3)に進みます。
  • 現在のノードは3です。
  • 2 < 3なので、左の子ノードに挿入します。
  • 左の子ノードはnilなので、Insertメソッドは新しいノードを作成します。
  • val2です。
  • 新しいノードが作成され、2がその値になります。
   5
  / \
  3  10
 / \  / \
 2 nil nil
/ \
nil nil

最終的な木の構造

全ての挿入操作が完了した後、最終的な二分探索木の構造は次のようになります。

   5
  / \
  3  10
 / \
 2 nil
/ \
nil nil

結果

  • 5がルートノード。
  • 35の左の子ノード。
  • 105の右の子ノード。
  • 23の左の子ノード。
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?