排序算法總結(jié)

冒泡排序(Bubble sort)

是一種簡(jiǎn)單的排序算法。它重復(fù)地遍歷要排序的數(shù)列,一次比較兩個(gè)元素,如果他們的順序錯(cuò)誤就把他們交換過(guò)來(lái)。遍歷數(shù)列的工作是重復(fù)地進(jìn)行直到?jīng)]有再需要交換,也就是說(shuō)該數(shù)列已經(jīng)排序完成。這個(gè)算法的名字由來(lái)是因?yàn)樵叫〉脑貢?huì)經(jīng)由交換慢慢“浮”到數(shù)列的頂端。

冒泡排序算法的運(yùn)作如下:
  • 比較相鄰的元素。如果第一個(gè)比第二個(gè)大(升序),就交換他們。
  • 對(duì)每一個(gè)相鄰元素作同樣的工作,從開(kāi)始第一對(duì)到結(jié)尾的最后一對(duì)。這步做完后,最后的元素會(huì)是最大的數(shù)。
  • 針對(duì)所有的元素重復(fù)以上的步驟,除了最后一個(gè)。
  • 持續(xù)每次對(duì)越來(lái)越少的元素重復(fù)上面的步驟,直到?jīng)]有任何一對(duì)數(shù)字需要比較。
時(shí)間復(fù)雜度
  • 最優(yōu):O(n)(表示遍歷一次發(fā)現(xiàn)沒(méi)有任何可以交換的元素,排序結(jié)束。)
  • 最壞:O(n2)
  • 穩(wěn)定性:穩(wěn)定
def bubble_sort(alist):
    """冒泡排序"""
    n = len(alist)
    #for j in range(n-1,0,-1):
    #    for i in range(j):
    for j in range(n-1):
        # 記錄是否交換過(guò)
        count = 0
        for i in range(0, n - 1 - j):
            # 班長(zhǎng)從頭走到尾
            if alist[i] > alist[i+1]:
                alist[i],alist[i+1] = alist[i+1],alist[i]
                count += 1
        if count == 0:
            return 

選擇排序(Selection sort)

是一種簡(jiǎn)單直觀的排序算法。它的工作原理如下。首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再?gòu)氖S辔磁判蛟刂欣^續(xù)尋找最小(大)元素,然后放到已排序序列的末尾。以此類推,直到所有元素均排序完畢。
選擇排序的主要優(yōu)點(diǎn)與數(shù)據(jù)移動(dòng)有關(guān)。如果某個(gè)元素位于正確的最終位置上,則它不會(huì)被移動(dòng)。選擇排序每次交換一對(duì)元素,它們當(dāng)中至少有一個(gè)將被移到其最終位置上,因此對(duì)n個(gè)元素的表進(jìn)行排序總共進(jìn)行至多n-1次交換。在所有的完全依靠交換去移動(dòng)元素的排序方法中,選擇排序?qū)儆诜浅:玫囊环N。

時(shí)間復(fù)雜度
  • 最優(yōu):O(n2)
  • 最壞:O(n2)
  • 穩(wěn)定性:不穩(wěn)定(考慮升序每次選擇最大的情況)
def select_sort(alist):
    """選擇排序"""
    n = len(alist)
    for j in range(n-1): # j: 0 ~ n-2
        min_index = j
        for i in range(j+1, n):
            if alist[min_index] > alist[i]:
                min_index = i

        alist[j], alist[min_index] = alist[min_index], alist[j]

插入排序(Insertion sort)

是一種簡(jiǎn)單直觀的排序算法。它的工作原理是通過(guò)構(gòu)建有序序列,對(duì)于未排序數(shù)據(jù),在已排序序列中從后向前掃描,找到相應(yīng)位置并插入。插入排序在實(shí)現(xiàn)上,在從后向前掃描過(guò)程中,需要反復(fù)把已排序元素逐步向后挪位,為最新元素提供插入空間。

時(shí)間復(fù)雜度
  • 最優(yōu):O(n)(升序排列,序列已經(jīng)處于升序狀態(tài))
  • 最壞:O(n2)
  • 穩(wěn)定性:穩(wěn)定
def insert_sort(alist):
    """插入排序"""
    n = len(alist)
    # 從右邊的無(wú)序序列中取出多少個(gè)元素執(zhí)行這樣的過(guò)程
    for j in range(1, n): # j : 1 ~ n-1
        # i 代表內(nèi)層循環(huán)的起始值
        i = j
        # 執(zhí)行從右邊的無(wú)序序列中取出第一個(gè)元素,即i位置的元素,然后將其插入到前面的正確位置中
        while i > 0:
            if alist[i] < alist[i-1]:
                alist[i], alist[i-1] = alist[i-1], alist[i]
                i -= 1
            else:
                break

希爾排序(Shell sort)

是插入排序的一種。也稱縮小增量排序,是直接插入排序算法的一種更高效的改進(jìn)版本。希爾排序是非穩(wěn)定排序算法。是把記錄按下標(biāo)的一定增量分組,對(duì)每組使用直接插入排序算法排序,隨著增量逐漸減少,每組包含的關(guān)鍵詞越來(lái)越多,當(dāng)增量減至1時(shí),整個(gè)文件恰被分成一組,算法便終止。

時(shí)間復(fù)雜度
  • 最優(yōu):O(n1.3)
  • 最壞:O(n2)
  • 穩(wěn)定性:不穩(wěn)定
def shell_sort(alist):
    # n = 9
    n = len(alist)
    # gap = 4
    gap = n // 2
    # gap變化到0之前,插入算法執(zhí)行的次數(shù)
    while gap > 0:
        # 插入算法,與普通的插入算法的區(qū)別就是gap步長(zhǎng)
        for j in range(gap, n):
            # j = [gap, gap+1, gap+2, ..., n-1]
            i = j
            while i > 0:
                if alist[i] < alist[i - gap]:
                    alist[i], alist[i - gap] = alist[i - gap], alist[i]
                    i -= gap
                else:
                    break

        gap //= 2

快速排序(Quick sort)

是對(duì)冒泡排序的一種改進(jìn)。通過(guò)一趟排序?qū)⒁判虻臄?shù)據(jù)分割成獨(dú)立的兩部分,其中一部分的所有數(shù)據(jù)都比另外一部分的所有數(shù)據(jù)都要小,然后再按此方法對(duì)這兩部分?jǐn)?shù)據(jù)分別進(jìn)行快速排序,整個(gè)排序過(guò)程可以遞歸進(jìn)行,以此達(dá)到整個(gè)數(shù)據(jù)變成有序序列。

快速排序的基本思想是:
  1. 先從數(shù)列中取出一個(gè)數(shù)作為基準(zhǔn)數(shù)
  2. 分區(qū)過(guò)程,將比這個(gè)數(shù)大的數(shù)全放到它的右邊,小于或等于它的數(shù)全放到它的左邊
  3. 再對(duì)左右區(qū)間重復(fù)第二步,直到各區(qū)間只有一個(gè)數(shù)
時(shí)間復(fù)雜度
  • 最優(yōu):O(nlogn)
  • 最壞:O(n2)
  • 穩(wěn)定性:不穩(wěn)定
def quick_sort(alist, first, last):
    """快速排序"""
    # 遞歸退出條件
    if first >= last:
        return
    mid_value = alist[first]
    low = first
    high = last

    while low < high:
        # high 左移
        while low < high and alist[high] >= mid_value:
            high -= 1
        alist[low] = alist[high]

        # low 右移
        while low < high and alist[low] < mid_value:
            low += 1
        alist[high] = alist[low]
    # 從循環(huán)退出時(shí),low == high
    alist[low] = mid_value

    # 對(duì)low左邊的列表執(zhí)行快速排序
    quick_sort(alist, first, low - 1)

    #  對(duì)low右邊的列表執(zhí)行快速排序
    quick_sort(alist, low + 1, last)

歸并排序(Merge sort)

是采用分治法的一個(gè)非常典型的應(yīng)用。歸并排序的思想就是先遞歸分解數(shù)組,再合并數(shù)組。
將數(shù)組分解最小之后,然后合并兩個(gè)有序數(shù)組,基本思路是比較兩個(gè)數(shù)組的最前面的數(shù),誰(shuí)小就先取誰(shuí),取了后相應(yīng)的指針就往后移一位。然后再比較,直至一個(gè)數(shù)組為空,最后把另一個(gè)數(shù)組的剩余部分復(fù)制過(guò)來(lái)即可。

時(shí)間復(fù)雜度
  • 最優(yōu):O(nlogn)
  • 最壞:O(nlogn)
  • 穩(wěn)定性:穩(wěn)定
def merge_sort(alist):
    """歸并排序"""
    n = len(alist)
    if n<= 1:
        return alist
    mid = n//2

    # left 采用歸并排序后形成的有序的新的列表
    left_li = merge_sort(alist[:mid])

    # right 采用歸并排序后形成的有序的新的列表
    right_li = merge_sort(alist[mid:])

    # 將兩個(gè)有序的子序列合并為一個(gè)新的整體
    left_pointer, right_pointer = 0, 0
    result = []

    while left_pointer < len(left_li) and right_pointer < len(right_li):
        if left_li[left_pointer] <= right_li[right_pointer]:
            result.append(left_li[left_pointer])
            left_pointer += 1
        else:
            result.append(right_li[right_pointer])
            right_pointer += 1

    result += left_li[left_pointer:]
    result += right_li[right_pointer:]
    return result
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.簡(jiǎn)介插入排序(Insertion Sort)的算法描述是一種簡(jiǎn)單直觀的排序算法。它的工作原理是通過(guò)構(gòu)建有序序列...
    AngerCow閱讀 492評(píng)論 0 1
  • 7種常用的排序算法總結(jié) 2016.04.30PoetryAlgorithm 排序算法:一種能將一串?dāng)?shù)據(jù)依照特定的排...
    raining_804f閱讀 867評(píng)論 0 0
  • 簡(jiǎn)單排序 冒泡排序:循環(huán)遍歷左右比較,較小者左移或較大者后移; 選擇排序:在未排序序列中找到最小者元素一次放到已排...
    王然Gondole閱讀 1,482評(píng)論 0 2
  • 淺談?wù)n堂導(dǎo)入的設(shè)計(jì) 導(dǎo)入新課是課堂教學(xué)的一個(gè)重要環(huán)節(jié),俗話說(shuō),良好的開(kāi)端是成功的一半,運(yùn)用恰當(dāng)?shù)姆椒▽?dǎo)入新課,能夠...
    云淡風(fēng)輕歲月安好閱讀 229評(píng)論 0 0
  • 今天筆記內(nèi)容,有一句,永遠(yuǎn)不要用簡(jiǎn)單的結(jié)果,取代成長(zhǎng)的樂(lè)趣!我們要快樂(lè)完成結(jié)果。我覺(jué)得這很重要!
    冰咋吃閱讀 125評(píng)論 0 2

友情鏈接更多精彩內(nèi)容