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

Commit 446385d

Browse files
feat: add implementations for various sorting algorithms and Euclidean algorithm
1 parent a51f356 commit 446385d

10 files changed

Lines changed: 179 additions & 13 deletions

File tree

math/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# 数学ぽいやつ
2+
3+
## ユークリッドの互助法
4+
5+
## エラトステネスのふるい

math/eratosthenes.hs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
primes :: [Int]
2+
primes = 2 : sieve [3, 5 ..] -- 2と奇数の無限配列
3+
where
4+
sieve (p : xs) =
5+
p
6+
: sieve
7+
[ x
8+
| x <- xs,
9+
x `mod` p /= 0
10+
]
11+
12+
main :: IO ()
13+
main = do
14+
print $ take 20 primes
15+
print $ 7 `elem` primes
16+
17+
-- print $ 102 `elem` primes -- 素数でない数を探索すると止まらない

math/euclidean.hs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
-- ユークリッドの互助法
2+
euclidean :: Int -> Int -> Int
3+
euclidean a b
4+
| a `mod` b == 0 = b
5+
| otherwise = euclidean b (a `mod` b)
6+
7+
main :: IO ()
8+
main = do
9+
print $ euclidean 5 21
10+
print $ euclidean 10 100
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
main :: IO ()
2+
main = do
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
linearSearch :: [Int] -> Int -> Int
2+
linearSearch xs target =
3+
head
4+
[ i
5+
| i <- [0 .. length xs - 1],
6+
xs !! i == target
7+
]
8+
9+
main :: IO ()
10+
main = do
11+
let randomList = [30, 75, 69, 16, 47, 77, 60, 80, 74, 8, 77, 1, 60, 33, 70, 29, 24, 91, 60, 69]
12+
print randomList
13+
let target = 77
14+
print $ linearSearch randomList 77

sort/README.md

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,15 @@
44

55
- 隣り合う要素の大小を比較しながら整列させる。
66
- アルゴリズムが単純で実装が用意なため、並列処理との親和性が高い。
7-
- バブルソートを 1 回行うと最後の要素が最大になるため、次回のスキャン範囲を 1 狭めることができる。
8-
- そのため、平均計算時間は、n-1+n-2...1=n(n-1)/2 である。
9-
- よって計算量は O(n^2)
10-
- 最後に要素の交換を行った位置から、スキャン範囲の最後の要素にたどり着くまでの間に連続して要素の交換が発生しない場合にはスキャン回数を大幅に狭めることができる。--> つまり、ソート済みの部分があると実行速度が上がる。
7+
- バブルソートを 1 回行うと右端(もしくは左端)の要素がソートされるため、次回のスキャン範囲を 1 狭めることができる。
8+
- 最良ケース、平均ケース、最悪ケースともにO(n^2) (交換回数ではなく、比較回数)
9+
- n - 1 + n - 2 ... 1 = n(n - 1) / 2 = (n^2 - n) / 2
10+
11+
### 実装例
12+
13+
- [x] C
14+
- [x] Python
15+
- [x] Haskell
1116

1217
---
1318

@@ -21,6 +26,12 @@
2126
- 最悪ケース(逆順に整列されている場合)はO(n^2)
2227
- i番目の挿入で毎回右端まで移動するので、1 + 2 + 3 ... + (n-1) = n(n-1)/2 回の比較が必要になる。
2328

29+
### 実装例
30+
31+
- [x] C
32+
- [x] Python
33+
- [x] Haskell
34+
2435
---
2536

2637
## 選択ソート(Selection Sort)
@@ -30,13 +41,21 @@
3041
- リストサイズを n とすると、1 回目は n 回の探索、2 回目は n-1 回の探索が必要になる。そのため、ステップ数は n + (n-1) + (n -2) ... 1 = n(n+1)/2  となる。
3142
- よって計算量は O(n^2)となる。
3243

44+
### 実装例
45+
46+
- [x] C
47+
- [x] Python
48+
- [x] Haskell
49+
3350
---
3451

3552
## マージゾート(Merge Sort)
3653

37-
- 2 つのソート済みの配列をつなげてソートする方法。配列を 1 個ずつに分解して,マージする過程で順番を並べることを繰り返す。
38-
- そのため,まず配列をサイズ 1 まで小さくしてそれを結合する過程でマージする操作を繰り返す。
39-
- 問題を細かく分割し、簡単な問題を解くことを積み重ねて全体の回を得るマージソートのような問題を分割統治法(divide-and-conquer method)と呼ぶ。
54+
- 2 つのソート済みの配列をつなげてソートする方法。配列をサイズ1まで一度分解し,マージする過程で順番を並べることを繰り返す。
55+
- 最良ケース、平均ケース、最悪ケースともにO(nlog2 n)である。
56+
57+
> [!NOTE]
58+
> 問題を細かく分割し、簡単な問題を解くことを積み重ねて全体の回を得るマージソートのような問題を分割統治法(divide-and-conquer method)と呼ぶ。
4059
4160
### マージソートの計算量
4261

@@ -54,7 +73,7 @@
5473
- この木の高さ log2 n に対して、2 分木の高さを半分にするには,おおよそ n/2 回のマージが必用である。
5574
- このことからマージソートの計算量は O(nlog2 n) であることがわかる。
5675

57-
### スターリングの近似
76+
#### スターリングの近似
5877

5978
> [スターリングの近似](https://ja.wikipedia.org/wiki/%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%AA%E3%83%B3%E3%82%B0%E3%81%AE%E8%BF%91%E4%BC%BC)
6079
@@ -65,20 +84,36 @@
6584
- つまり,2^k >= (n/e)^n \* √(2πn) である。
6685
- これを変形して,k >= nlog2 n - nlog2 e + 1/2log2(2πn) であるためマージソートの計算量は理論上最小であることがわかる。
6786

87+
### 実装例
88+
89+
- [x] C
90+
- [x] Python
91+
- [x] Haskell
92+
6893
---
6994

7095
## クイックソート(Quick Sort)
7196

7297
- マージソートと同じ分割統治法(divide-and-conquer method)に分類される。
7398
- 配列から pivot を選択し、pivot より小さいか大きいかで配列を 2 つに分割し,分割した配列それぞれに対してこの操作を繰り返していくことでソートされる。
74-
- クイックソートは pivot からソート完了後の位置に配置されていく。
75-
- 計算量は O(nlog2 n)
76-
> [!NOTE]
77-
> クイックソートは高速だが,ピボットの位置を固定している場合にパフォーマンスが落ちてしまうことがある。これは,ピボットで配列を 2 つに分割した時に片方に配列のサイズが大きくなってしまった場合にパフォーマンスが悪くなる。
78-
> つまり,ソート済みの配列に対しては毎回分割が発生するため,1 + 2 + 3 ... n-1 = (n)(n-1)/2 となるため最悪計算量は O(n^2)である。
99+
- 計算量は最良ケースでは、O(nlog2 n)
100+
- 平均ケースでも、O(nlog2 n)
101+
- 最悪ケースでは、O(n^2)
102+
103+
> [!NOTE]
104+
> クイックソートは高速だが,ピボットの位置を固定している場合にパフォーマンスが落ちてしまうことがある。
105+
> これは,ピボットで配列を 2 つに分割した時に片方に配列のサイズが大きくなってしまった場合にパフォーマンスが悪くなる。
106+
> 左端をピボッドにするとした場合には,ソート済みの配列に対しては毎回分割が発生するため,1 + 2 + 3 ... n-1 = (n)(n-1)/2 となるため最悪計算量は O(n^2)である。
107+
79108
- そこで pivot をランダムに選択するようにすることで、パフォーマンスが劇的に低下することを防ぐことができる。
80109
- このようにアルゴリズムの実行にランダムな要素を含むものを乱択アルゴリズムという。
81110

111+
### 実装例
112+
113+
- [x] C
114+
- [x] Python
115+
- [x] Haskell
116+
82117
---
83118

84119
## シェルソート(Shell Sort)
@@ -89,6 +124,12 @@
89124
- h-ソート: 前処理として一定の距離(h)離れた要素を比較し,ソートする。
90125
- この例では h を 3n+1 としてループを回す毎に h を 3 で割る(切り捨て)しつつ,挿入ソートと同様に 2 つの値を比較して並べることを繰り返す。
91126

127+
### 実装例
128+
129+
- [x] C
130+
- [x] Python
131+
- [] Haskell
132+
92133
---
93134

94135
## ヒープソート(Heap Sort)

sort/bubble_sort/bubbleSort.hs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
bubbleSort :: (Ord a) => [a] -> [a]
2+
bubbleSort xs =
3+
-- リストの数だけ再帰する
4+
go xs (length xs)
5+
where
6+
go xs 0 = xs
7+
go xs n = go (bubble xs) (n - 1)
8+
9+
-- 隣同士を比較して交換する関数
10+
bubble (x : y : zs)
11+
| x > y = y : bubble (x : zs)
12+
| otherwise = x : bubble (y : zs)
13+
bubble xs = xs -- リストのサイズが2未満になった時
14+
15+
main :: IO ()
16+
main = do
17+
let randomList = [30, 75, 69, 16, 47, 77, 60, 80, 74, 8, 77, 1, 60, 33, 70, 29, 24, 91, 60, 69]
18+
print randomList
19+
print $ bubbleSort randomList

sort/merge_sort/mergeSort.hs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
mergeSort :: [Int] -> [Int]
2+
mergeSort [] = []
3+
mergeSort [x] = [x]
4+
mergeSort xs = merge (mergeSort left) (mergeSort right) -- 配列をサイズ1もしくは空になるまで分割する
5+
where
6+
(left, right) = splitAt (length xs `div` 2) xs -- 真ん中でリストを分割する
7+
8+
-- 配列を合成する過程でソートする
9+
merge :: [Int] -> [Int] -> [Int]
10+
merge [] ys = ys
11+
merge xs [] = xs
12+
merge (x : xs) (y : ys)
13+
| x <= y = x : merge xs (y : ys)
14+
| otherwise = y : merge (x : xs) ys
15+
16+
main :: IO ()
17+
main = do
18+
let randomList = [30, 75, 69, 16, 47, 77, 60, 80, 74, 8, 77, 1, 60, 33, 70, 29, 24, 91, 60, 69]
19+
print randomList
20+
print $ mergeSort randomList

sort/quick_sort/quickSort.hs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
-- NOTE: pivotは雑に左端から選択している
2+
quickSort :: (Ord a) => [a] -> [a]
3+
quickSort [] = []
4+
quickSort (x : xs) = quickSort left ++ [x] ++ quickSort right
5+
where
6+
left = filter (< x) xs
7+
right = filter (>= x) xs
8+
9+
main :: IO ()
10+
main = do
11+
let randomList = [30, 75, 69, 16, 47, 77, 60, 80, 74, 8, 77, 1, 60, 33, 70, 29, 24, 91, 60, 69]
12+
print randomList
13+
print $ quickSort randomList
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import Data.List (delete, unfoldr)
2+
3+
selectionSort :: (Ord a) => [a] -> [a]
4+
selectionSort xs =
5+
go xs
6+
where
7+
go [] = []
8+
go xs = let m = minimum xs in m : go (delete m xs) -- deleteで特定の要素を消した配列を返している
9+
10+
-- unfoldrを使って簡潔に書いたバージョン
11+
selectionSort' :: (Ord a) => [a] -> [a]
12+
selectionSort' xs = unfoldr go xs
13+
where
14+
go [] = Nothing -- 空なら停止
15+
go xs =
16+
let m = minimum xs
17+
xs' = delete m xs
18+
in Just (m, xs')
19+
20+
main :: IO ()
21+
main = do
22+
let randomList = [30, 75, 69, 16, 47, 77, 60, 80, 74, 8, 77, 1, 60, 33, 70, 29, 24, 91, 60, 69]
23+
print randomList
24+
print $ selectionSort randomList
25+
print $ selectionSort' randomList

0 commit comments

Comments
 (0)