我在B站學python之排序算法2

1.希爾排序

在上一篇,我們講了插入排序, 也是一種基於比較的排序。其實還有一個大佬提出一種改進的插入排序:希爾排序(shell sort)。
希爾排序的思想是:

先對序列進行分組,每次尋求一個gap:例如:
2 1 3 5 9 1 6 8
length = 8
gap = length / 2 = 4
就分成4組: 然後對每一組進行插入排序。

例如:
2 1 3 5 9 1 6 8
然後對每一組進行插入排序:

2       9         --- 插入排序
  1       1       --- 插入排序
    3       6     --- 插入排序
      5       8   --- 插入排序
2 1 3 5 9 1 6 8 

雖然每一組字面上來說,根本不需要排序。
接着,gap = gap / 2,如此繼續執行上述操作。

這樣做,可以減少插入排序的次數

算法複雜度和穩定性:

希爾排序的時間複雜度是: O(nlogn) O(n2)O(nlogn) ~ O(n^2) 最好情況: O(n13)O(n^{1-3)} 最壞情況: O(n2)O(n^2) 不需要佔用多餘的空間,空間複雜度O(1);是不穩定排序。
python版本的實現:

def shell_sort(self, list):
    """
    希爾排序,希爾排序基於插入排序,不過是先對序列進行分組
    然後對分組執行插入排序
    :return: 插入排序的結果
    """
    n = len(list)
    gap = n // 2
    while gap >= 1:
        ## 插入排序
        for i in range(0, n - gap):
        		## 讓間隔gap的元素爲一組
            j = i + gap
            while j > 0:
                if list[j] < list[j - gap]:
                    (list[j - gap], list[j]) = (list[j], list[j - gap])
                    j -= gap
                else:
                    break
        ## gap折半,直至1
        gap = gap // 2
    ## 返回結果
    return list

2. 快速排序

快速排序的思想是一種基於分治的思想:

先找一個樞點,把序列分成兩部分,一部分全都不小於該樞點,一部分全都大於該樞點。
然後對這兩部分再進行快排

這個過程中,就採用了分而治之思想,化複雜爲簡單。

快排的時間複雜度是:Onlogn)O(nlogn) 他的排序過程,就不再演示了。這裏直接給出算法複雜度分析:

算法複雜度和穩定性:

希爾排序的時間複雜度是 O(nlogn) O(nlogn) 最好情況, O(nlogn) O(nlogn) 最壞情況: O(n2)O(n^2) 不需要佔用多餘的空間,空間複雜度O(1);是不穩定排序。

python版本的代碼實現:

def quick_sort(self, list, first, end):
    """
    快速排序 基於分治的思想,找到一個值,把比這個元素小的,分成左邊部分;
    把比這個元素大的,分成右邊部分。
    接着對左邊部分和右邊部分,分別進行快速排序
    :param list:
    :param first:
    :param end:
    :return:
    """
    low = first
    high = end
    pivot = list[low]

    if low >= high:
        return

    while low < high:
        while low < high and list[high] >= pivot:
            high -= 1
        list[low] = list[high]

        while low < high and list[low] < pivot:
            low += 1
        list[high] = list[low]
    ## 此時,low == high, 把elment放在low指向的元素
    list[low] = pivot
    print(list)
    self.quick_sort(list, first, low - 1)
    self.quick_sort(list, low + 1, end)

3.歸併排序

歸併排序的思想是:先拆分序列,直到不能拆分的單個元素;然後把每個元素當作一個序列,他們分別都是有序的。那麼兩兩合併,非常容易,因爲是有序序列:

例如:5 8 1 2,拆分成4個數組: [5], [8] ,[1], [2]。接着兩兩合併成:

[5 8]

[1 2]

接着,就複雜一點,兩個索引:up, down,分別指向 5, 1:

up 
|
5   8                  

down
|
1   2
合併結果: 【1】
   
down
|
5  8

  up
   | 
   2

結果: 【1,2】
把剩餘5和8放入數組,結果:【1,2,5,8】

算法複雜度和穩定性:

希爾排序的平均時間複雜度是 O(nlogn) O(nlogn) 最好情況, O(nlogn) O(nlogn) 最壞情況:O(nlogn) O(nlogn) 需要佔用最多長度爲n的空間,空間複雜度O(n) O(n)
希爾排序是穩定排序。

python版本的代碼實現:

def merge_sort(self, list):
    """
    歸併排序的實現
    :param self:
    :param list:
    :return:
    """
    n = len(list)
    if n == 1:
        return list
    mid = n // 2
    print("mid:", mid)
    left = self.merge_sort(list[:mid])
    right = self.merge_sort(list[mid:])
    print("left list:", left)
    print("right list:", right)
    result = self.merge(left, right)

    return result

def merge(self, left_list, right_list):
    """
    合併兩個列表
    :param right_list:
    :return:
    """
    list = []
    left = 0
    right = 0
    left_len = len(left_list)
    right_len = len(right_list)

    print("merge, left len:", left_len, "right_len:", right_len)
    while left < left_len and right < right_len:
        if left_list[left] < right_list[right]:
            list.append(left_list[left])
            left += 1
        else:
            list.append(right_list[right])
            right += 1

    ## 把剩餘的元素移動到list中
    if left < left_len:
        while left < left_len:
            list.append(left_list[left])
            left += 1

    if right < right_len:
        while right < right_len:
            list.append(right_list[right])
            right += 1
    return list

總結

各種算法的分析和總結:

排序算法 平均情況 最好情況 最壞情況 輔助空間 穩定性
冒泡排序 O(n2)O(n^2) O(n) O(n2)O(n^2) O(1) 穩定
選擇排序 O(n2)O(n^2) O(n2)O(n^2) O(n2)O(n^2) O(1) 不穩定
插入排序 O(n2)O(n^2) O(n) O(n2)O(n^2) O(1) 穩定
希爾排序 O(nlogn) ~ O(n2)O(n^2) O(n13)O(n^{1-3)} O(n2)O(n^2) O(1) 不穩定
堆排序 O(nlogn) O(nlogn) O(nlogn) O(1) 穩定
歸併排序 O(nlogn) O(nlogn) O(nlogn) O(n) 穩定
快速排序 O(nlogn) O(nlogn) O(n2)O(n^2) O(nlogn) ~ O(n) 不穩定
發佈了63 篇原創文章 · 獲贊 29 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章