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

Commit 031669d

Browse files
feat: hash example
1 parent 7d47606 commit 031669d

6 files changed

Lines changed: 121 additions & 56 deletions

File tree

data_structure/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,23 @@
2828
## 連結リスト(linked list)
2929

3030
- 各データが次のデータのへの参照情報としてリンク(ポインタ)を持つデータ構造。
31+
32+
---
33+
34+
## ハッシュテーブル
35+
36+
- データの挿入時にはハッシュ関数によってデータを格納するインデックスを決定する。O(1)
37+
- データの存在確認時、削除時にはハッシュ関数によってデータが格納されているインデックスを決定し、そのインデックスに格納されているデータを確認する。O(1)
38+
39+
### 実装例
40+
41+
[チェイン法](https://www.ei.fukui-nct.ac.jp/2019/01/08/hash-chain/)による実装
42+
43+
> [!NOTE]
44+
> 同じハッシュ値のデータをグループ化して保存する。この実装では同じハッシュ値のデータはリストで保存している。
45+
46+
- [x] Haskell
47+
48+
---
49+
50+
## ツリー(Tree)

data_structure/hash/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# ハッシュテーブル(Hash Table)
2+
3+
## HOW TO RUN
4+
5+
```shell
6+
runghc -package=hashable hash.hs
7+
```
8+
9+
## 概要

data_structure/hash/hash.hs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import Data.Hashable (Hashable, hash)
2+
import Data.Vector qualified as V
3+
import Debug.Trace (trace, traceShowId)
4+
5+
dbgId :: (Show a) => a -> a
6+
dbgId x = trace ("bucketIndex is " ++ show x) x
7+
8+
-- チェイン法によるハッシュ
9+
-- NOTE: レコード構文を使い、buckets hsで値が取得できるようにしている
10+
-- ghci> import Data.Vector qualified as V
11+
-- ghci> data HashSet a = HashSet {buckets :: V.Vector [a]} deriving (Show)
12+
-- ghci> hs = HashSet {buckets=(V.replicate 3 [])}
13+
-- ghci> buckets hs
14+
-- [[],[],[]]
15+
data HashSet a = HashSet {buckets :: V.Vector [a]}
16+
deriving (Show)
17+
18+
-- どのindexに保存するかを決める
19+
bucketIndex :: (Hashable a) => HashSet a -> a -> Int
20+
bucketIndex hs x = abs (hash x) `mod` V.length (buckets hs)
21+
22+
-- ハッシュテーブルの初期化
23+
empty :: Int -> HashSet a
24+
empty size = HashSet (V.replicate size [])
25+
26+
-- 値の存在確認
27+
member :: (Eq a, Hashable a) => a -> HashSet a -> Bool
28+
member x hs = x `elem` bucket -- NOTE: チェイン法なので同じハッシュの値が含まれている可能性があるのでelemでチェックしている
29+
where
30+
i = bucketIndex hs x
31+
bucket = buckets hs V.! i
32+
33+
insert :: (Eq a, Hashable a) => a -> HashSet a -> HashSet a
34+
insert x hs
35+
| member x hs = hs -- 同じ要素は格納しない
36+
| otherwise = hs {buckets = buckets hs V.// [(i, x : bucket)]} -- index iの要素をx:bucketに置き換える(チェイン法なので同じハッシュの値は維持)
37+
where
38+
i = dbgId $ bucketIndex hs x
39+
bucket = buckets hs V.! i
40+
41+
delete :: (Eq a, Hashable a) => a -> HashSet a -> HashSet a
42+
delete x hs =
43+
hs {buckets = buckets hs V.// [(i, newBucket)]}
44+
where
45+
i = dbgId $ bucketIndex hs x
46+
bucket = buckets hs V.! i
47+
newBucket = filter (/= x) bucket
48+
49+
main :: IO ()
50+
main = do
51+
let hs0 = empty 8 :: HashSet Int -- サイズ8
52+
print hs0
53+
54+
-- insert
55+
print "insert 1 4"
56+
let hs1 = insert 1 hs0
57+
hs2 = insert 4 hs1
58+
print hs2
59+
60+
-- check
61+
print "check 10 1 is store"
62+
print $ member 10 hs2 -- False
63+
print $ member 1 hs2 -- True
64+
65+
-- delete
66+
print "delete 1 and check 1 4 is store"
67+
let hs2' = delete 1 hs2
68+
print hs2'
69+
print $ member 1 hs2' -- False
70+
print $ member 4 hs2 -- True
71+
72+
-- 同じハッシュのときのチェック
73+
print "same hash"
74+
let hs3 = insert 16 hs2
75+
hs4 = insert 32 hs3
76+
print hs4

data_structure/tree/tree.hs

Lines changed: 1 addition & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1 @@
1-
-- https://www.sampou.org/haskell/article/whyfp.html より
2-
data Tree a = Node a [Tree a]
3-
4-
-- 木のリストに対する畳み込み
5-
redtree ::
6-
(a -> b -> b) -> -- f : node を潰す
7-
(b -> b -> b) -> -- g : cons を潰す
8-
b -> -- a : nil を潰す
9-
Tree a ->
10-
b
11-
redtree f g a (Node label subtrees) =
12-
f label (redtree' f g a subtrees)
13-
14-
-- ツリーのリストを処理する関数
15-
redtree' ::
16-
(a -> b -> b) ->
17-
(b -> b -> b) ->
18-
b ->
19-
[Tree a] ->
20-
b
21-
redtree' f g a (subtree : rest) =
22-
g
23-
(redtree f g a subtree) -- リストのサイズが1に分解して潰す --> f label (redtree' f g a [先頭の木]) ...という流れでredtree' _ _ a [] = aにたどりつく
24-
(redtree' f g a rest) -- 残りで再帰
25-
redtree' _ _ a [] =
26-
a
27-
28-
tree :: Tree Int
29-
tree =
30-
Node
31-
1
32-
( (:)
33-
(Node 2 [])
34-
( (:)
35-
( Node
36-
3
37-
((:) (Node 4 []) [])
38-
)
39-
[]
40-
)
41-
)
42-
43-
sumtree :: (Num a) => Tree a -> a
44-
sumtree tree = redtree (+) (+) 0 tree
45-
46-
labels :: (Num a) => Tree a -> [a]
47-
labels tree = redtree (:) (++) [] tree
48-
49-
maptree :: (a -> b) -> Tree a -> Tree b
50-
maptree f tree = redtree (\label subtrees -> Node (f label) subtrees) (:) [] tree
51-
52-
main :: IO ()
53-
main = do
54-
print $ sumtree tree -- 10
55-
print $ labels tree -- [1, 2, 3, 4]
56-
print $ maptree (* 2) tree
1+
-- TODO

flake.nix

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
ps.vector
2828
ps.containers
2929
ps.bytestring
30+
ps.unordered-containers
31+
ps.hashable
3032
]))
3133
pkgs.haskell.packages.ghc96.cabal-install
3234
pkgs.haskell.packages.ghc96.haskell-language-server

hie.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
cradle:
2+
direct:
3+
arguments:
4+
- -package
5+
- hashable
6+
- -package
7+
- vector
8+
- -package
9+
- containers
10+
- -package
11+
- bytestring
12+
- -package
13+
- unordered-containers

0 commit comments

Comments
 (0)