Skip to content
This repository was archived by the owner on May 22, 2026. It is now read-only.

Commit d87a8dd

Browse files
feat: bst
1 parent f229dbe commit d87a8dd

2 files changed

Lines changed: 153 additions & 0 deletions

File tree

search/README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,18 @@
5454

5555
## BST(Binary Search Tree)
5656

57+
- 二分木探索とも。
58+
- 各ノードに値が格納されており、左の子ノードは親ノードより小さい値、右の子ノードは親ノードより大きい値を持つという構造を維持する二分木。
59+
- ノードの削除時には、そのノードの右部分木の最小値を持つノードを削除するノードの位置に移動させることで、BSTの構造を維持する。
60+
- 右部分技の最小値は、左部分木のどの値よりも大きいが、右部分木のどの値よりも小さいため、BSTの構造が維持される。
61+
- (右部分木の最小値は、子ノードがないので移動させやすい。)
62+
63+
### 実装例
64+
65+
- [ ] C
66+
- [ ] Python
67+
- [x] Haskell
68+
5769
---
5870

5971
## bit 全探索(bit search)

search/bst/bst.hs

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
{-# LANGUAGE CPP #-}
2+
{-# LANGUAGE OverloadedStrings #-}
3+
4+
-- {-# OPTIONS_GHC -DATCODER #-}
5+
import Debug.Trace (traceShowId)
6+
7+
#ifdef ATCODER
8+
debug :: Bool ; debug = False
9+
#else
10+
debug :: Bool ; debug = True
11+
#endif
12+
13+
dbgId :: (Show a) => a -> a
14+
dbgId x
15+
| debug = traceShowId x
16+
| otherwise = x
17+
18+
data BST a
19+
= Empty
20+
| Node a (BST a) (BST a)
21+
deriving (Show)
22+
23+
search :: (Ord a) => a -> BST a -> Bool
24+
search _ Empty = False
25+
search target (Node v left right)
26+
| target == v = True
27+
| target < v = search target left -- 自分より小さい値は左側の枝に
28+
| otherwise = search target right
29+
30+
insert :: (Ord a) => a -> BST a -> BST a
31+
insert x Empty = Node x Empty Empty
32+
insert x (Node v left right)
33+
| x == v = Node v left right
34+
| x < v = Node v (insert x left) right
35+
| otherwise = Node v left (insert x right)
36+
37+
-- 削除対象の位置にその位置からみた右部分木の最小値に置き換える。
38+
-- これにより、左部分技よりは小さく、右部分技のどの値よりも小さな値がトップにくるため二分木が破綻しない。
39+
delete :: (Ord a) => a -> BST a -> BST a
40+
delete _ Empty = Empty
41+
delete x (Node v left right)
42+
| x < v = Node v (delete x left) right
43+
| x > v = Node v left (delete x right)
44+
| otherwise = removeNode (Node v left right)
45+
46+
-- ノード削除ロジック
47+
removeNode :: (Ord a) => BST a -> BST a
48+
removeNode (Node _ Empty right) = right
49+
removeNode (Node _ left Empty) = left
50+
removeNode (Node _ left right) =
51+
-- 右部分木の最小値を取り出し、そのノードを除いた木も返す
52+
let (m, right') = detachMin right
53+
in Node m left right'
54+
removeNode Empty = Empty
55+
56+
detachMin :: BST a -> (a, BST a)
57+
detachMin Empty = error "detachMin: empty tree"
58+
detachMin (Node x Empty right) = (x, right)
59+
detachMin (Node x left right) =
60+
let (m, left') = detachMin left
61+
in (m, Node x left' right)
62+
63+
-- 木を整形して表示(枝を使って階層構造を明確化)
64+
prettyPrint :: (Show a) => BST a -> String
65+
prettyPrint tree = go "" "" tree
66+
where
67+
go _ _ Empty = ""
68+
go prefix childPrefix (Node x left right) =
69+
prefix
70+
++ show x
71+
++ "\n"
72+
++ drawChildren childPrefix left right
73+
74+
drawChildren prefix Empty Empty = ""
75+
drawChildren prefix left Empty =
76+
go (prefix ++ "└── ") (prefix ++ " ") left
77+
drawChildren prefix Empty right =
78+
go (prefix ++ "└── ") (prefix ++ " ") right
79+
drawChildren prefix left right =
80+
go (prefix ++ "├── ") (prefix ++ "") left
81+
++ go (prefix ++ "└── ") (prefix ++ " ") right
82+
83+
main :: IO ()
84+
main = do
85+
let bTree =
86+
Node
87+
5
88+
( Node
89+
3
90+
( Node
91+
1
92+
Empty
93+
Empty
94+
)
95+
( Node
96+
4
97+
Empty
98+
Empty
99+
)
100+
)
101+
( Node
102+
7
103+
( Node
104+
6
105+
Empty
106+
Empty
107+
)
108+
( Node
109+
8
110+
Empty
111+
Empty
112+
)
113+
)
114+
putStrLn "=====INITIAl====="
115+
putStrLn $ prettyPrint bTree
116+
print $ search 3 bTree -- 存在する
117+
print $ search 10 bTree -- 存在しない
118+
119+
-- 追加
120+
putStrLn "=====ADD 10====="
121+
let bTree' = insert 10 bTree
122+
putStrLn $ prettyPrint bTree'
123+
print $ search 10 bTree'
124+
125+
-- 存在する要素を追加
126+
putStrLn "=====ADD 3(already exists)====="
127+
let bTree'' = insert 3 bTree
128+
putStrLn $ prettyPrint bTree''
129+
print $ search 3 bTree''
130+
131+
-- 削除
132+
putStrLn "=====DELETE 5====="
133+
let bTree''' = delete 5 bTree
134+
putStrLn $ prettyPrint bTree'''
135+
print $ search 5 bTree'''
136+
137+
-- 存在しない要素を削除する
138+
putStrLn "=====DELETE 8(not exist)====="
139+
let bTree'''' = delete 8 bTree
140+
putStrLn $ prettyPrint bTree''''
141+
print $ search 8 bTree''''

0 commit comments

Comments
 (0)