Pythonは8大ソートアルゴリズム(転載)+バケツソート(オリジナル)を実現


  • ソートの挿入
  • 核心思想
  • コード実装
  • ヒルソート
  • 核心思想
  • コード実装
  • バブルソート
  • 核心思想
  • コード実装
  • クイックソート
  • 核心思想
  • コード実装
  • 直接選択ソート
  • 核心思想
  • コード実装
  • スタック・ソート
  • 核心思想
  • コード実装
  • 集計ソート
  • 核心思想
  • コード実装
  • 基数ソート
  • 核心思想
  • コード実装
  • バレルソート
  • 核心思想
  • コード実装
  • 試験結果
  • まとめ

  • ソートアルゴリズムの重要性は言うまでもない.ここで1編抜粋して、ここに転載して、学習鑑賞に供する.
    ソートの挿入
    核心思想.
    ソートを挿入する基本的な操作は、1つのデータを並べ替えられたソートデータに挿入し、新しい、個数に1を加えたソートデータを得ることであり、アルゴリズムは少量のデータのソートに適用され、時間複雑度はO(n^2)である.安定したソート方法です.挿入アルゴリズムは、ソートする配列を2つの部分に分けます.第1の部分には、この配列のすべての要素が含まれていますが、最後の要素を除いて(配列の複数の空間に挿入された位置があるようにします)、第2の部分には、この要素(すなわち、挿入される要素)しか含まれていません.最初の部分のソートが完了したら、最後の要素をソートされた最初の部分に挿入します.
    コード実装
    def insert_sort(lists): 
        #      
        count = len(lists) 
        for i in range(1, count): 
            key = lists[i] 
            j = i - 1 
            while j >= 0: 
                if lists[j] > key: 
                    lists[j + 1] = lists[j] 
                    lists[j] = key 
                j -= 1 
        return lists

    ヒルソート
    核心思想.
    ヒルソート(Shell Sort)は、ソートを挿入するものです.インクリメンタルソートの縮小とも呼ばれ、ソートアルゴリズムを直接挿入するより効率的な改良バージョンです.ヒルソートは非安定ソートアルゴリズムである.この方法はDL.Shellが1959年に提案したことから名付けられた.ヒルソートは、レコードを下付きの一定の増分でグループ化し、各グループに対して直接挿入ソートアルゴリズムを使用してソートする.増分が減少するにつれて、各グループに含まれるキーワードはますます多くなり、増分が1に減少すると、ファイル全体がグループに分けられ、アルゴリズムは終了する.
    コード実装
    def shell_sort(lists): 
        #      
        count = len(lists) 
        step = 2 
        group = count / step 
        while group > 0: 
            for i in range(0, group): 
                j = i + group 
                while j < count: 
                    k = j - group 
                    key = lists[j] 
                    while k >= 0: 
                        if lists[k] > key: 
                            lists[k + group] = lists[k] 
                            lists[k] = key 
                        k -= group 
                    j += group 
            group /= step 
        return lists

    バブルソート
    核心思想.
    ソートする数列を繰り返し訪問し、2つの要素を一度に比較し、順序が間違っている場合は交換します.数列を訪問する作業は、交換が必要になるまで繰り返し、すなわち、その数列がソートされるまで行われる.
    コード実装
    def bubble_sort(lists): 
        #      
        count = len(lists) 
        for i in range(0, count): 
            for j in range(i + 1, count): 
                if lists[i] > lists[j]: 
                    lists[i], lists[j] = lists[j], lists[i] 
        return lists

    クイックソート
    核心思想.
    1回のソートでソートするデータを独立した2つの部分に分割し、一部のすべてのデータが他の部分のすべてのデータよりも小さくなり、この方法で2つの部分のデータをそれぞれ迅速にソートし、ソートプロセス全体を再帰的に行うことで、データ全体が秩序化されたシーケンスになるようにします.
    コード実装
    def quick_sort(lists, left, right): 
        #      
        if left >= right: 
            return lists 
        key = lists[left] 
        low = left 
        high = right 
        while left < right: 
            while left < right and lists[right] >= key: 
                right -= 1 
            lists[left] = lists[right] 
            while left < right and lists[left] <= key: 
                left += 1 
            lists[right] = lists[left] 
        lists[right] = key 
        quick_sort(lists, low, left - 1) 
        quick_sort(lists, left + 1, high) 
        return lists

    直接選択ソート
    核心思想.
    基本思想:第1回目は、ソート待ち記録r 1~r[n]の中から最小の記録を選択し、r 1と交換する.2回目は、ソート対象レコードr 2~r[n]の中から最小のレコードを選択し、r 2と交換する.このように,i回目はソート対象レコードr[i]~r[n]の中で最小のレコードを選択し,r[i]と交換し,すべてのソートが完了するまで秩序シーケンスを成長させる.
    コード実装
    def select_sort(lists): 
        #      
        count = len(lists) 
        for i in range(0, count): 
            min = i 
            for j in range(i + 1, count): 
                if lists[min] > lists[j]: 
                    min = j 
            lists[min], lists[i] = lists[i], lists[min] 
        return lists

    ヒープのソート
    核心思想.
    スタックソート(Heapsort)とは、スタックツリー(スタック)というデータ構造を用いて設計されたソートアルゴリズムであり、ソートを選択するものである.配列の特徴を使用して、指定したインデックスの要素をすばやく配置できます.山は大根の山と小根の山に分かれていて、完全に二叉木です.ルートスタックの要件は、各ノードの値が親ノードの値より大きくないことです.すなわち、A[PROD[i]>=A[i]です.配列の非降順ソートでは、大きなスタックが使用される必要があります.大きなスタックの要求によって、最大の値は必ずスタックの頂上にあることがわかります.
    コード実装
    #     
    def adjust_heap(lists, i, size): 
        lchild = 2 * i + 1 
        rchild = 2 * i + 2 
        max = i 
        if i < size / 2: 
            if lchild < size and lists[lchild] > lists[max]: 
                max = lchild 
            if rchild < size and lists[rchild] > lists[max]: 
                max = rchild 
            if max != i: 
                lists[max], lists[i] = lists[i], lists[max] 
                adjust_heap(lists, max, size) 
    
    #     
    def build_heap(lists, size): 
        for i in range(0, (size/2))[::-1]: 
            adjust_heap(lists, i, size) 
    
    #     
    def heap_sort(lists): 
        size = len(lists) 
        build_heap(lists, size) 
        for i in range(0, size)[::-1]: 
            lists[0], lists[i] = lists[i], lists[0] 
            adjust_heap(lists, 0, i)

    集計ソート
    核心思想.
    集計ソートは集計操作に確立された有効なソートアルゴリズムであり,このアルゴリズムは分割法(Divide and Conquer)を用いた非常に典型的な応用である.既存のシーケンスのサブシーケンスを結合し、完全に秩序化されたシーケンスを得る.すなわち、各サブシーケンスを秩序化してから、サブシーケンスセグメント間を秩序化する.2つの順序テーブルを1つの順序テーブルに結合すると、2ウェイ集計と呼ばれます.
    集計プロセスは、a[i]とa[j]のサイズを比較し、a[i]≦a[j]の場合、最初の秩序テーブルの要素a[i]をr[k]にコピーし、iとkにそれぞれ1を加算する.そうでなければ、2番目の順序テーブルの要素a[j]をr[k]にコピーし、jとkにそれぞれ1を加算し、そのうちの1つの順序テーブルが終わるまでループし、その後、別の順序テーブルの残りの要素をrの下付きkから下付きtのユニットにコピーする.集計ソートのアルゴリズムは通常再帰的に実現され,まずソート対象区間[s,t]を中点二分し,次に左サブ区間をソートし,右サブ区間をソートし,最後に左区間と右区間を一次集計操作で秩序ある区間[s,t]に統合する.
    コード実装
    def merge(left, right): 
        i, j = 0, 0 
        result = [] 
        while i < len(left) and j < len(right): 
            if left[i] <= right[j]: 
                result.append(left[i]) 
                i += 1 
            else: 
                result.append(right[j]) 
                j += 1 
        result += left[i:] 
        result += right[j:] 
        return result 
    
    def merge_sort(lists): 
        #      
        if len(lists) <= 1: 
            return lists 
        num = len(lists) / 2 
        left = merge_sort(lists[:num]) 
        right = merge_sort(lists[num:]) 
        return merge(left, right)

    ベースソート
    核心思想.
    基数ソート(radix sort)は「分配式ソート」(distribution sort)に属し、「バケツ法」(bucket sort)またはbin sortとも呼ばれる.名前の通り、キー値の一部の情報を通して、ソートする要素をいくつかの「バケツ」に割り当て、ソートの役割を果たすために、基数ソート法は安定性のソートに属し、その時間複雑度はO(nlog(r)m)である.ここで、rは採用された基数であり、mはスタック数であり、場合によっては、基数ソート法の効率は他の安定性ソート法よりも高い.
    コード実装
    import math 
    def radix_sort(lists, radix=10): 
        k = int(math.ceil(math.log(max(lists), radix))) 
        bucket = [[] for i in range(radix)] 
        for i in range(1, k+1): 
            for j in lists: 
                bucket[j/(radix**(i-1)) % (radix**i)].append(j) 
            del lists[:] 
            for z in bucket: 
                lists += z 
                del z[:] 
        return lists

    以上、他の人のよく使うソートアルゴリズムを転載しましたが、もちろんソートアルゴリズムの実現についてはまだまだたくさんありますが、ここでは「バケツソート」に関する小さな例を書いてみましょう.
    バケツソート
    核心思想.
    スペースと時間を節約するには、ソートするデータの最小値と最大値を指定して、便器ソートアルゴリズムの演算を行う必要があります.
    コード実装
    # coding:utf-8
    import sys
    
    reload(sys)
    sys.setdefaultencoding('utf8')
    # __author__ = '   '
    # __date__ = '2016/9/6'
    # __Desc__ =      ,    
    
    def sort(arr):
        result = []
        for index in range(0,len(arr)):
            result.append(0)
        for index in range(len(arr)):
            counter = result[arr[index]]+1
            result[arr[index]]=counter
        return result
    
    if __name__ == '__main__':
        arr = [1,3,5,7,9,2,9,4,6,8,0,1,1,3,2,2,2,2]
        arr = sort(arr)
        for item in range(len(arr)):
            if arr[item]!=0:
                step = arr[item]
                while step>0:
                    print item,
                    step-=1

    テスト結果
    D:\Software\Python2\python.exe E:/Code/Python/DataStructor/temp/BarrelSort.py
    0 1 1 1 2 2 2 2 2 3 3 4 5 6 7 8 9 9
    
    Process finished with exit code 0
    

    まとめ
    以上、大牛が完成した古典的な8大ソートアルゴリズムと、自分が実現した簡単なバケツソートに関する小さなケースを紹介した.