Files
hello-algo/ja/codes/swift/chapter_tree/binary_search_tree.swift
Yudong Jin 7257641e0e Retranslate the complete Japanese online edition from Chinese (#2008)
* Retranslate the complete Japanese online edition from Chinese

* Fit Japanese homepage labels and localize heading permalinks

* Point Japanese contribution instructions to the Japanese preview

* Replace locale conditionals with multilingual UI tables
2026-10-30 02:12:26 +08:00

174 lines
5.4 KiB
Swift
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* File: binary_search_tree.swift
* Created Time: 2023-01-26
* Author: nuomi1 (nuomi1@qq.com)
*/
import utils
/* 二分探索木 */
class BinarySearchTree {
private var root: TreeNode?
/* コンストラクタ */
init() {
// 空の木を初期化する
root = nil
}
/* 二分木の根ノードを取得する */
func getRoot() -> TreeNode? {
root
}
/* ノードを探索する */
func search(num: Int) -> TreeNode? {
var cur = root
// 繰り返し探索し、葉ノードを越えたら終了する
while cur != nil {
// 目的のノードは cur の右部分木にある
if cur!.val < num {
cur = cur?.right
}
// 目的のノードは cur の左部分木にある
else if cur!.val > num {
cur = cur?.left
}
// 目的のノードが見つかったので、ループを終了する
else {
break
}
}
// 目的のノードを返す
return cur
}
/* ノードを挿入する */
func insert(num: Int) {
// 木が空の場合、根ノードを初期化する
if root == nil {
root = TreeNode(x: num)
return
}
var cur = root
var pre: TreeNode?
// 繰り返し探索し、葉ノードを越えたら終了する
while cur != nil {
// 重複したノードが見つかったので、そのまま戻る
if cur!.val == num {
return
}
pre = cur
// 挿入位置は cur の右部分木にある
if cur!.val < num {
cur = cur?.right
}
// 挿入位置は cur の左部分木にある
else {
cur = cur?.left
}
}
// ノードを挿入する
let node = TreeNode(x: num)
if pre!.val < num {
pre?.right = node
} else {
pre?.left = node
}
}
/* ノードを削除する */
func remove(num: Int) {
// 木が空の場合、そのまま早期リターンする
if root == nil {
return
}
var cur = root
var pre: TreeNode?
// 繰り返し探索し、葉ノードを越えたら終了する
while cur != nil {
// 削除対象のノードが見つかったので、ループを終了する
if cur!.val == num {
break
}
pre = cur
// 削除対象のノードは cur の右部分木にある
if cur!.val < num {
cur = cur?.right
}
// 削除対象のノードは cur の左部分木にある
else {
cur = cur?.left
}
}
// 削除対象のノードが存在しない場合、そのまま戻る
if cur == nil {
return
}
// 子ノード数 = 0 または 1
if cur?.left == nil || cur?.right == nil {
// 子ノード数 = 0 / 1 の場合、child = null / その子ノード
let child = cur?.left ?? cur?.right
// ノード cur を削除する
if cur !== root {
if pre?.left === cur {
pre?.left = child
} else {
pre?.right = child
}
} else {
// 削除するノードが根ノードの場合、根ノードを指定し直す
root = child
}
}
// 子ノード数 = 2
else {
// 通りがけ順で cur の次のノードを取得する
var tmp = cur?.right
while tmp?.left != nil {
tmp = tmp?.left
}
// ノード tmp を再帰的に削除する
remove(num: tmp!.val)
// tmp で cur を上書きする
cur?.val = tmp!.val
}
}
}
@main
enum _BinarySearchTree {
/* 実行用コード */
static func main() {
/* 二分探索木を初期化する */
let bst = BinarySearchTree()
// 挿入順序が異なると異なる二分木になることに注意。この順序ではパーフェクト二分木を生成できる
let nums = [8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15]
for num in nums {
bst.insert(num: num)
}
print("\n初期化した二分木\n")
PrintUtil.printTree(root: bst.getRoot())
/* ノードを探索する */
let node = bst.search(num: 7)
print("\n見つかったノードオブジェクトは \(node!)、ノードの値 = \(node!.val)")
/* ノードを挿入する */
bst.insert(num: 16)
print("\nノード 16 を挿入した後の二分木\n")
PrintUtil.printTree(root: bst.getRoot())
/* ノードを削除する */
bst.remove(num: 1)
print("\nノード 1 を削除した後の二分木\n")
PrintUtil.printTree(root: bst.getRoot())
bst.remove(num: 2)
print("\nノード 2 を削除した後の二分木\n")
PrintUtil.printTree(root: bst.getRoot())
bst.remove(num: 4)
print("\nノード 4 を削除した後の二分木\n")
PrintUtil.printTree(root: bst.getRoot())
}
}