今回はPython言語で
様々なソートプログラムを実装して
色々比較してみました。
解説動画はこちら
今回は
さてひとつづつ見ていきましょう。
バブルソート(Bubble Sort)
データの量が少ない場合や
すでにほぼソートされている場合には
高速に動作するようです。
マージソート(Merge Sort)
安定かつ効率的なアルゴリズムであり
大きなデータセットに対しても
高速に動作するそうです。
クイックソート(Quick Sort)
一般的に高速でメモリ効率も良いですが
最悪の場合には効率が落ちることがあるそうです。
再帰を用いたものと
再帰無しバージョンがあり
検証は無しバージョンを使用してます。
再帰無し
ヒープソート(Heap Sort)
安定でありながらも効率的なソートが可能ですが
実装がやや複雑です。
シェルソート(Shell Sort)
これら7つのソートプログラムを用いて
速度を比較してみましょう。
こちらのコードで比較検証を行いました。
最後に
とまあ、ソートプログラムを書くのは
プログラミングのお勉強には良いですが
業務上の実益はほぼほぼ無いですねー
そもそもPythonの組み込みソートは
圧倒的に性能が良く
数10万件程度だと
誤差の範囲で終わってしまうので
ソートを業務で実装することは
余り無いですね。
超大規模なデータを用いるような
大掛かりなプロジェクトでなければ
ソートに手を入れて高速化をはかるような
案件に出会えないですかね。
興味がある方は
突き詰めてみるのも面白いかもです。
今回はこれまでです
それでは。
様々なソートプログラムを実装して
色々比較してみました。
解説動画はこちら
今回は
ソートプログラムを比較してみる検証です。
用意したソートプログラムは
こんなのです。
用意したソートプログラムは
こんなのです。
1.バブルソート(Bubble Sort)
2.選択ソート(Selection Sort)
3.挿入ソート(Insertion Sort)
4.マージソート(Merge Sort)
5.クイックソート(Quick Sort)
6.ヒープソート(Heap Sort)
7.シェルソート(Shell Sort)
さてひとつづつ見ていきましょう。
バブルソート(Bubble Sort)
隣接する要素を比較して順番が逆であれば交換を行う
比較的単純なソートアルゴリズムで
比較的単純なソートアルゴリズムで
効率はあまりよくなく、実装が容易です。
選択ソート(Selection Sort)
バブルソートよりも効率的です。
挿入ソート(Insertion Sort)
# バブルソート def bubble_sort(arr): n = len(arr) for i in range(n): for j in range(0, n-i-1): if arr[j] > arr[j+1]: arr[j], arr[j+1] = arr[j+1], arr[j] return arr
選択ソート(Selection Sort)
配列を走査し、最小値を見つけて
先頭の要素と交換することを繰り返すことで
ソートを行うアルゴリズム
先頭の要素と交換することを繰り返すことで
ソートを行うアルゴリズム
バブルソートよりも効率的です。
# 選択ソート def selection_sort(arr): n = len(arr) for i in range(n): min_index = i for j in range(i+1, n): if arr[j] < arr[min_index]: min_index = j arr[i], arr[min_index] = arr[min_index], arr[i] return arr
要素を1つずつ取り出して
適切な位置に挿入していくことで
ソートを行うアルゴリズム
適切な位置に挿入していくことで
ソートを行うアルゴリズム
データの量が少ない場合や
すでにほぼソートされている場合には
高速に動作するようです。
# 挿入ソート def insertion_sort(arr): for i in range(1, len(arr)): key = arr[i] j = i - 1 while j >= 0 and key < arr[j]: arr[j + 1] = arr[j] j -= 1 arr[j + 1] = key return arr
分割統治法を用いた再帰的なアルゴリズムで
データを分割してソートし、それをマージすることで
ソートを行うアルゴリズム
データを分割してソートし、それをマージすることで
ソートを行うアルゴリズム
安定かつ効率的なアルゴリズムであり
大きなデータセットに対しても
高速に動作するそうです。
def merge_sort(arr): if len(arr) > 1: mid = len(arr) // 2 left_half = arr[:mid] right_half = arr[mid:] merge_sort(left_half) merge_sort(right_half) i = j = k = 0 while i < len(left_half) and j < len(right_half): if left_half[i] < right_half[j]: arr[k] = left_half[i] i += 1 else: arr[k] = right_half[j] j += 1 k += 1 while i < len(left_half): arr[k] = left_half[i] i += 1 k += 1 while j < len(right_half): arr[k] = right_half[j] j += 1 k += 1 return arr
分割統治法を用いた再帰的なアルゴリズムで
ピボットを選択し、それを基準にデータを分割して
ソートするアルゴリズム
ピボットを選択し、それを基準にデータを分割して
ソートするアルゴリズム
一般的に高速でメモリ効率も良いですが
最悪の場合には効率が落ちることがあるそうです。
再帰を用いたものと
再帰無しバージョンがあり
検証は無しバージョンを使用してます。
# クイックソート(再帰あり) def quick_sort(arr): if len(arr) <= 1: return arr else: pivot = arr[0] left = [x for x in arr[1:] if x < pivot] right = [x for x in arr[1:] if x >= pivot] return quick_sort(left) + [pivot] + quick_sort(right)
再帰無し
# 再帰なし def quick_sort(arr): size = len(arr) stack = [(0, size - 1)] while stack: start, end = stack.pop() if start >= end: continue pivot = arr[end] low = start high = end - 1 while low <= high: if arr[low] > pivot and arr[high] < pivot: arr[low], arr[high] = arr[high], arr[low] low += 1 high -= 1 if arr[low] <= pivot: low += 1 if arr[high] >= pivot: high -= 1 arr[low], arr[end] = arr[end], arr[low] if low - start < end - low: stack.append((start, low - 1)) stack.append((low + 1, end)) else: stack.append((low + 1, end)) stack.append((start, low - 1)) return arr
ヒープソート(Heap Sort)
ヒープと呼ばれる特殊なデータ構造を使用して
ソートを行うアルゴリズム
ソートを行うアルゴリズム
安定でありながらも効率的なソートが可能ですが
実装がやや複雑です。
def heapify(arr, n, i): largest = i left = 2 * i + 1 right = 2 * i + 2 if left < n and arr[i] < arr[left]: largest = left if right < n and arr[largest] < arr[right]: largest = right if largest != i: arr[i], arr[largest] = arr[largest], arr[i] heapify(arr, n, largest) # ヒープソート def heap_sort(arr): n = len(arr) for i in range(n // 2 - 1, -1, -1): heapify(arr, n, i) for i in range(n - 1, 0, -1): arr[i], arr[0] = arr[0], arr[i] heapify(arr, i, 0) return arr
挿入ソートの改良版であり
データを一定の間隔で分割して
ソートを行うアルゴリズム
データを一定の間隔で分割して
ソートを行うアルゴリズム
間隔を縮めながら繰り返し処理を行うことで
最終的にソートされた配列が得られます。
速度比較最終的にソートされた配列が得られます。
# シェルソート def shell_sort(arr): n = len(arr) gap = n // 2 while gap > 0: for i in range(gap, n): temp = arr[i] j = i while j >= gap and arr[j - gap] > temp: arr[j] = arr[j - gap] j -= gap arr[j] = temp gap //= 2 return arr
これら7つのソートプログラムを用いて
速度を比較してみましょう。
こちらのコードで比較検証を行いました。
import numpy as np import time import sys sys.setrecursionlimit(20000) # 関数実行時間チェック def time_check(name,func,n): start_time = time.time() val = func(n); end_time = time.time() print(name, end_time - start_time) # ソート比較 def compare_sort(n): # ソート対象のリスト生成 arr = [1 for _ in range(n)] np.random.shuffle(arr) # 各ソートアルゴリズムの実行時間計測 #time_check("バブルソート" , bubble_sort, arr.copy()) #time_check("選択ソート" , selection_sort, arr.copy()) time_check("挿入ソート" , insertion_sort, arr.copy()) #time_check("マージソート" , merge_sort, arr.copy()) time_check("クイックソート" , quick_sort, arr.copy()) time_check("ヒープソート" , heap_sort, arr.copy()) time_check("シェルソート" , shell_sort, arr.copy()) compare_sort(1000)
最後に
とまあ、ソートプログラムを書くのは
プログラミングのお勉強には良いですが
業務上の実益はほぼほぼ無いですねー
そもそもPythonの組み込みソートは
圧倒的に性能が良く
数10万件程度だと
誤差の範囲で終わってしまうので
ソートを業務で実装することは
余り無いですね。
超大規模なデータを用いるような
大掛かりなプロジェクトでなければ
ソートに手を入れて高速化をはかるような
案件に出会えないですかね。
興味がある方は
突き詰めてみるのも面白いかもです。
今回はこれまでです
それでは。
コメントする