排序算法總結(jié)與 Py 實現(xiàn)

排序算法總結(jié)與 Py 實現(xiàn)

這篇文章主要借鑒了地址,原文是 Java 實現(xiàn)的,質(zhì)量特別棒。


算法分類:

常見排序算法一般分為兩大類:

  • 比較型排序:通過比較決定元素的相對次序,由于其時間復(fù)雜度不能突破O(nlogn),因此也稱為非線性時間比較類排序。
  • 非比較排序::不通過比較來決定元素間的相對次序,它可以突破基于比較排序的時間下界,以線性時間運行,因此也稱為線性時間非比較類排序。


    排序算法.png

算法復(fù)雜度

算法復(fù)雜度.png


相關(guān)概念

  • 穩(wěn)定:即元素的相對順序是否會發(fā)生改變,如 a 原本在 b 前面,而 a=b,排序之后 a 仍然在 b 的前面,則算法是穩(wěn)定的。有些算法由于判斷條件是 >=<= ,這個條件包含了相等的狀態(tài),這會導(dǎo)致該元素會落在最后的位置。
  • 不穩(wěn)定:如果a原本在b的前面,而a=b,排序之后 a 可能會出現(xiàn)在 b 的后面。有些算法由于判斷條件是 >=<= ,這個條件包含了相等的狀態(tài),這會導(dǎo)致該元素會落在最后的位置。

穩(wěn)定舉例:比如你考試成績一直和班里的另一個同學(xué)相同,那么穩(wěn)定的排序算法就是每次總排名你都在他前頭,而不是這次他排你前頭,下次你排他前頭。

  • 時間復(fù)雜度:對排序數(shù)據(jù)的總的操作次數(shù)。
  • 空間復(fù)雜度:是指算法在計算機(jī)
    內(nèi)執(zhí)行時所需存儲空間的度量,它也是數(shù)據(jù)規(guī)模n的函數(shù)。

1、冒泡排序

冒泡排序是一種遍歷的排序算法。它重復(fù)地走過要排序的數(shù)列,一次比較兩個元素,如果它們的順序錯誤就把它們交換過來。每次遍歷都會把一個值放到合適的位置。

1.1 算法描述

  • 比較相鄰的元素。如果第一個比第二個大,就交換它們兩個;
  • 對每一對相鄰元素作同樣的工作,從開始第一對到結(jié)尾的最后一對,這樣在最后的元素應(yīng)該會是最大的數(shù);
  • 針對所有的元素重復(fù)以上的步驟,除了最后一個;
  • 重復(fù)步驟1~3,直到排序完成。
    1.2 圖示
    冒泡.png
冒泡.png

1.3 代碼

def mao(nums):
    n = len(nums)
    for i in range(n):
    # n個數(shù),遍歷 n 次
        for j in range(n-i-1):
        # 因為每次遍歷都會放一個數(shù)到合適的位置,所以 - i,
        # 又因為是在比較 nums[j] 與 nums[j+1],j+1的操作可以幫住我們上擴(kuò)大遍歷的范圍,所以 - 1
            if nums[j] > nums[j+1]:
            # 注意這里是 > 號,所以不會交換相同的值,所以冒泡是穩(wěn)定的算法
                nums[j], nums[j+1] = nums[j+1], nums[j]
        print(nums)
    return nums          

2、快速排序

快速排序的基本思想:通過一趟排序?qū)⒋庞涗浄指舫瑟毩⒌膬刹糠郑渲幸徊糠钟涗浀年P(guān)鍵字均比另一部分的關(guān)鍵字小,則可分別對這兩部分記錄繼續(xù)進(jìn)行排序,以達(dá)到整個序列有序。
2.1 算法描述

快速排序使用分治法來把一個串(list)分為兩個子串(sub-lists)。具體算法描述如下:

從數(shù)列中挑出一個元素,稱為 “基準(zhǔn)”(pivot);
重新排序數(shù)列,所有元素比基準(zhǔn)值小的擺放在基準(zhǔn)前面,所有元素比基準(zhǔn)值大的擺在基準(zhǔn)的后面(相同的數(shù)可以到任一邊)。在這個分區(qū)退出之后,該基準(zhǔn)就處于數(shù)列的中間位置。這個稱為分區(qū)(partition)操作;
遞歸地(recursive)把小于基準(zhǔn)值元素的子數(shù)列和大于基準(zhǔn)值元素的子數(shù)列排序。
2.2 圖示

快速排序.png

代碼

def quick(nums, left, right):
    if left < right:
        i, j = left, right
        i 是左指針,j 是右指針
        base = nums[i]
        #使用待排序列的第一個數(shù)做作為基數(shù)
        print(base)
        while i < j:    
            while i < j and nums[j] >= base:
            # j 會 pass 過所有大于等于 base 的值。注意這里也會 pass 過相等的值,這使得快速不是穩(wěn)定的算法
                j -= 1
            # 使 j 指針停在小于基數(shù)的位數(shù)
            nums[i] = nums[j]
            # 把 nums[j]的值 移到 i 的位置(讓小的數(shù)把前頭的值占了。)
            while i < j and nums[i] <= base:
                i += 1
            # 使 j 指針停在大于基數(shù)的位數(shù)
            nums[j] = nums[i]
            # 把 nums[i]的值 移到 j 的位置(讓大的數(shù)把后頭的值占了。)
        nums[i] = base
        # 在最后 i 會停在合適的位置,(左小右大),其實每次quick都只能保證一個數(shù)字排到合適的位置。
        print(i)
        # 使用遞歸把剩下的數(shù)列排序了
        quick(nums, left, i-1)
        quick(nums, i+1, right)
    return nums
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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