成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

基本排序算法的Python實現(xiàn)

zhangqh / 1471人閱讀

摘要:本篇主要實現(xiàn)九八大排序算法,分別是冒泡排序,插入排序,選擇排序,希爾排序,歸并排序,快速排序,堆排序計數(shù)排序。希爾排序是非穩(wěn)定排序算法。歸并排序算法依賴歸并操作。但是,計數(shù)排序可以用在基數(shù)排序算法中,能夠更有效的排序數(shù)據(jù)范圍很大的數(shù)組。

本篇主要實現(xiàn)九(八)大排序算法,分別是冒泡排序,插入排序,選擇排序,希爾排序,歸并排序,快速排序,堆排序,計數(shù)排序。希望大家回顧知識的時候也能從我的這篇文章得到幫助。

為了防止誤導讀者,本文所有概念性內(nèi)容均截取自對應Wiki

冒泡排序 原理

冒泡排序(Bubble Sort)是一種簡單的排序算法。它重復地走訪過要排序的數(shù)列,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來。走訪數(shù)列的工作是重復地進行直到?jīng)]有再需要交換,也就是說該數(shù)列已經(jīng)排序完成。這個算法的名字由來是因為越小的元素會經(jīng)由交換慢慢“浮”到數(shù)列的頂端。

步驟

冒泡排序算法的運作如下:

比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。

對每一對相鄰元素作同樣的工作,從開始第一對到結(jié)尾的最后一對。這步做完后,最后的元素會是最大的數(shù)。

針對所有的元素重復以上的步驟,除了最后一個。

持續(xù)每次對越來越少的元素重復上面的步驟,直到?jīng)]有任何一對數(shù)字需要比較。

代碼
def bubble_sort(list):
    length = len(list)
    # 第一級遍歷
    for index in range(length):
        # 第二級遍歷
        for j in range(1, length - index):
            if list[j - 1] > list[j]:
                # 交換兩者數(shù)據(jù),這里沒用temp是因為python 特性元組。
                list[j - 1], list[j] = list[j], list[j - 1]
    return list

這種排序其實還可以稍微優(yōu)化一下,添加一個標記,在排序已完成時,停止排序。

def bubble_sort_flag(list):
    length = len(list)
    for index in range(length):
        # 標志位
        flag = True
        for j in range(1, length - index):
            if list[j - 1] > list[j]:
                list[j - 1], list[j] = list[j], list[j - 1]
                flag = False
        if flag:
            # 沒有發(fā)生交換,直接返回list
            return list
    return list
選擇排序 原理

選擇排序(Selection sort)是一種簡單直觀的排序算法。它的工作原理大致是將后面的元素最小元素一個個取出然后按順序放置。

步驟

在未排序序列中找到最?。ù螅┰?,存放到排序序列的起始位置,

再從剩余未排序元素中繼續(xù)尋找最小(大)元素,然后放到已排序序列的末尾。

重復第二步,直到所有元素均排序完畢。

代碼
def selection_sort(list):
   n=len(list)
   for i in range (0,n):
       min = i
       for j in range(i+1,n):
           if list[j]
插入排序
原理

插入排序(Insertion Sort)是一種簡單直觀的排序算法。它的工作原理是通過構(gòu)建有序序列,對于未排序數(shù)據(jù),在已排序序列中從后向前掃描,找到相應位置并插入。

步驟

從第一個元素開始,該元素可以認為已經(jīng)被排序

取出下一個元素,在已經(jīng)排序的元素序列中從后向前掃描

如果該元素(已排序)大于新元素,將該元素移到下一位置

重復步驟3,直到找到已排序的元素小于或者等于新元素的位置

將新元素插入到該位置后

重復步驟2~5

代碼
def insert_sort(list):
    n = len(list)
    for i in range(1, n):
        # 后一個元素和前一個元素比較
        # 如果比前一個小
        if list[i] < list[i - 1]:
            # 將這個數(shù)取出
            temp = list[i]
            # 保存下標
            index = i
            # 從后往前依次比較每個元素
            for j in range(i - 1, -1, -1):
                # 和比取出元素大的元素交換
                if list[j] > temp:
                    list[j + 1] = list[j]
                    index = j
                else:
                    break
            # 插入元素
            list[index] = temp
    return list
希爾排序 原理

希爾排序,也稱遞減增量排序算法,是插入排序的一種更高效的改進版本。希爾排序是非穩(wěn)定排序算法。
希爾排序是基于插入排序的以下兩點性質(zhì)而提出改進方法的:
插入排序在對幾乎已經(jīng)排好序的數(shù)據(jù)操作時,效率高,即可以達到線性排序的效率
但插入排序一般來說是低效的,因為插入排序每次只能將數(shù)據(jù)移動一位。

步驟

每次以一定步長(就是跳過等距的數(shù))進行排序,直至步長為1.

代碼
def shell_sort(list):
    n = len(list)
    # 初始步長
    gap = round(n / 2)
    while gap > 0:
        for i in range(gap, n):
            # 每個步長進行插入排序
            temp = list[i]
            j = i
            # 插入排序
            while j >= gap and list[j - gap] > temp:
                list[j] = list[j - gap]
                j -= gap
            list[j] = temp
        # 得到新的步長
        gap = round(gap / 2)
    return list
步長使用的是Donald Shell的建議,另外步長還可以使用Sedgewick提出的(1, 5, 19, 41, 109,...)。
也可以使用斐波那契數(shù)列除去0和1將剩余的數(shù)以黃金分區(qū)比的兩倍的冪進行運算得到的數(shù)列。
歸并排序 原理

歸并操作(歸并算法),指的是將兩個已經(jīng)排序的序列合并成一個序列的操作。歸并排序算法依賴歸并操作。

步驟 迭代法

申請空間,使其大小為兩個已經(jīng)排序序列之和,該空間用來存放合并后的序列

設定兩個指針,最初位置分別為兩個已經(jīng)排序序列的起始位置

比較兩個指針所指向的元素,選擇相對小的元素放入到合并空間,并移動指針到下一位置

重復步驟3直到某一指針到達序列尾

將另一序列剩下的所有元素直接復制到合并序列尾

遞歸法

假設序列共有n個元素:

將序列每相鄰兩個數(shù)字進行歸并操作,形成 {displaystyle floor(n/2)} floor(n/2)個序列,排序后每個序列包含兩個元素

將上述序列再次歸并,形成 {displaystyle floor(n/4)} floor(n/4)個序列,每個序列包含四個元素

重復步驟2,直到所有元素排序完畢

代碼
# 遞歸法
def merge_sort(list):
    # 認為長度不大于1的數(shù)列是有序的
    if len(list) <= 1:
        return list
    # 二分列表
    middle = len(list) // 2
    left = merge_sort(list[:middle])
    right = merge_sort(list[middle:])
    # 最后一次合并
    return merge(left, right)
# 合并
def merge(left, right):
    l,r=0,0
    result=[]
    while l

鄙人不才,不知歸并排序的迭代法如何用Python實現(xiàn),望指教。

快速排序 原理

快速排序使用分治法(Divide and conquer)策略來把一個序列(list)分為兩個子序列(sub-lists)。

步驟

從數(shù)列中挑出一個元素,稱為"基準"(pivot),

重新排序數(shù)列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的后面(相同的數(shù)可以到任一邊)。在這個分區(qū)結(jié)束之后,該基準就處于數(shù)列的中間位置。這個稱為分區(qū)(partition)操作。

遞歸地(recursive)把小于基準值元素的子數(shù)列和大于基準值元素的子數(shù)列排序。

代碼

普通版

def quick_sort(list):
    less = []
    pivotList = []
    more = []
    # 遞歸出口
    if len(list) <= 1:
        return list
    else:
        # 將第一個值做為基準
        pivot = list[0]
        for i in list:
            # 將比急轉(zhuǎn)小的值放到less數(shù)列
            if i < pivot:
                less.append(i)
            # 將比基準打的值放到more數(shù)列
            elif i > pivot:
                more.append(i)
            # 將和基準相同的值保存在基準數(shù)列
            else:
                pivotList.append(i)
        # 對less數(shù)列和more數(shù)列繼續(xù)進行排序
        less = quick_sort(less)
        more = quick_sort(more)
        return less + pivotList + more

咳咳,下面這段代碼出自《Python cookbook 第二版》傳說中的三行實現(xiàn)python快速排序。

def qsort(arr):
    if len(arr) <= 1:
        return arr
    else:
        pivot = arr[0]
        return qsort([x for x in arr[1:] if x < pivot]) + 
               [pivot] + 
               qsort([x for x in arr[1:] if x >= pivot])

當然還有一行語法糖版本:

qs = lambda xs : ( (len(xs) <= 1 and [xs]) or [ qs( [x for x in xs[1:] if x < xs[0]] ) + [xs[0]] + qs( [x for x in xs[1:] if x >= xs[0]] ) ] )[0]

是不是感受到了Python的魅力?

堆排序 原理

堆排序(Heapsort)是指利用堆這種數(shù)據(jù)結(jié)構(gòu)所設計的一種排序算法。堆積是一個近似完全二叉樹的結(jié)構(gòu),并同時滿足堆積的性質(zhì):即子結(jié)點的鍵值或索引總是小于(或者大于)它的父節(jié)點。

步驟

創(chuàng)建最大堆:將堆所有數(shù)據(jù)重新排序,使其成為最大堆

最大堆調(diào)整:作用是保持最大堆的性質(zhì),是創(chuàng)建最大堆的核心子程序

堆排序:移除位在第一個數(shù)據(jù)的根節(jié)點,并做最大堆調(diào)整的遞歸運算

代碼
def heap_sort(list):
    # 創(chuàng)建最大堆
    for start in range((len(list) - 2) // 2, -1, -1):
        sift_down(list, start, len(list) - 1)

    # 堆排序
    for end in range(len(list) - 1, 0, -1):
        list[0], list[end] = list[end], list[0]
        sift_down(list, 0, end - 1)
    return list


# 最大堆調(diào)整
def sift_down(lst, start, end):
    root = start
    while True:
        child = 2 * root + 1
        if child > end:
            break
        if child + 1 <= end and lst[child] < lst[child + 1]:
            child += 1
        if lst[root] < lst[child]:
            lst[root], lst[child] = lst[child], lst[root]
            root = child
        else:
            break
計數(shù)排序 原理

當輸入的元素是n個0到k之間的整數(shù)時,它的運行時間是Θ(n + k)。計數(shù)排序不是比較排序,排序的速度快于任何比較排序算法。

由于用來計數(shù)的數(shù)組C的長度取決于待排序數(shù)組中數(shù)據(jù)的范圍(等于待排序數(shù)組的最大值與最小值的差加上1),這使得計數(shù)排序?qū)τ跀?shù)據(jù)范圍很大的數(shù)組,需要大量時間和內(nèi)存。例如:計數(shù)排序是用來排序0到100之間的數(shù)字的最好的算法,但是它不適合按字母順序排序人名。但是,計數(shù)排序可以用在基數(shù)排序算法中,能夠更有效的排序數(shù)據(jù)范圍很大的數(shù)組。

步驟

找出待排序的數(shù)組中最大和最小的元素

統(tǒng)計數(shù)組中每個值為i的元素出現(xiàn)的次數(shù),存入數(shù)組 C 的第 i 項

對所有的計數(shù)累加(從C中的第一個元素開始,每一項和前一項相加)

反向填充目標數(shù)組:將每個元素i放在新數(shù)組的第C(i)項,每放一個元素就將C(i)減去1

代碼
def count_sort(list):
    min = 2147483647
    max = 0
    # 取得最大值和最小值
    for x in list:
        if x < min:
            min = x
        if x > max:
            max = x
    # 創(chuàng)建數(shù)組C
    count = [0] * (max - min +1)
    for index in list:
        count[index - min] += 1
    index = 0
    # 填值
    for a in range(max - min+1):
        for c in range(count[a]):
            list[index] = a + min
            index += 1
    return list
第九種排序

None?
當然不會
自然就是系統(tǒng)自帶的

list.sort()

以上所有源代碼均在Github共享希望與大家共同進步!

參考資料

維基百科: 冒泡排序、選擇排序、插入排序、希爾排序、歸并排序、快速排序、堆排序、計數(shù)排序

Python Cookbook

感謝

知乎用戶:dhx1793516813、左鳶、靈劍
為本文缺漏之處提出建議

EOF

轉(zhuǎn)載請注明出處:http://eindex.me/post/base-so...
訪問原文「基本排序算法的Python實現(xiàn)」獲取最佳閱讀體驗并參與討論

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/38112.html

相關(guān)文章

  • python-八大算法

    摘要:排序算法總結(jié)排序算法平均時間復雜度冒泡排序選擇排序插入排序希爾排序快速排序歸并排序堆排序基數(shù)排序一冒泡排序基本思想兩個數(shù)比較大小,較大的數(shù)下沉,較小的數(shù)冒起來。 排序算法總結(jié) 排序算法 平均時間復雜度 冒泡排序O(n2) 選擇排序O(n2) 插入排序O(n2) 希爾排序O(n1.5) 快速排序O(N*logN) 歸并排序O(N*logN) 堆排序O(N*logN) 基數(shù)排序O(d(n+...

    aboutU 評論0 收藏0
  • Github標星2w+,熱榜第一,如何用Python實現(xiàn)所有算法

    摘要:歸并排序歸并排序,或,是創(chuàng)建在歸并操作上的一種有效的排序算法,效率為大符號。以此類推,直到所有元素均排序完畢。與快速排序一樣都由托尼霍爾提出的,因而也被稱為霍爾選擇算法。 showImg(https://segmentfault.com/img/remote/1460000019096360);編譯:周素云、蔣寶尚 學會了Python基礎(chǔ)知識,想進階一下,那就來點算法吧!畢竟編程語言只...

    zxhaaa 評論0 收藏0
  • 幾種排序算法Python 實現(xiàn)

    摘要:因為直接插入排序在元素基本有序的情況下接近最好情況,效率是很高的,因此希爾排序在時間效率上比前兩種方法有較大提高。 插入排序 def insert_sort(list): n = len(list) for i in range(1, n): key = list[i] for j in range(i-1, -1, -1): ...

    cod7ce 評論0 收藏0
  • 數(shù)據(jù)結(jié)構(gòu)與算法:常見排序算法

    摘要:這是一個簡單的遞歸函數(shù),你可以使用它來生成數(shù)列中指定序號的數(shù)值這個函數(shù)的問題在于它的執(zhí)行效率非常低有太多值在遞歸調(diào)用中被重新計算。 本章內(nèi)容銜接上一章 數(shù)據(jù)結(jié)構(gòu)與算法:二分查找 內(nèi)容提要 兩種基本數(shù)據(jù)結(jié)構(gòu): 數(shù)組 常見操作: 數(shù)組降維、數(shù)組去重 鏈表 遞歸:遞歸是很多算法都使用的一種編程方法   - 如何將問題分成基線條件和遞歸條件   - 分而治之策略解決棘手問題 ...

    wuyumin 評論0 收藏0
  • 數(shù)據(jù)結(jié)構(gòu)與算法:常見排序算法

    摘要:這是一個簡單的遞歸函數(shù),你可以使用它來生成數(shù)列中指定序號的數(shù)值這個函數(shù)的問題在于它的執(zhí)行效率非常低有太多值在遞歸調(diào)用中被重新計算。 本章內(nèi)容銜接上一章 數(shù)據(jù)結(jié)構(gòu)與算法:二分查找 內(nèi)容提要 兩種基本數(shù)據(jù)結(jié)構(gòu): 數(shù)組 常見操作: 數(shù)組降維、數(shù)組去重 鏈表 遞歸:遞歸是很多算法都使用的一種編程方法   - 如何將問題分成基線條件和遞歸條件   - 分而治之策略解決棘手問題 ...

    Carson 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<