Python 中的歸併排序

歸併排序類似於快速排序算法,因為它基於分治的概念。它是最流行和最有效的排序算法之一。這是分而治之類算法的最好例子。

它將給定的列表分成兩半,調用自己的兩半,然後合併兩個已排序的一半。我們定義 merge() 函數用於合併兩個半體。

子列表被一次又一次地分成兩半,直到我們每個都只得到一個元素。然後,我們將一對元素列表組合成兩個元素列表,在這個過程中排序它們。排序後的兩個元素對被合併到四個元素列表中,以此類推,直到我們得到排序後的列表。

歸併排序概念

讓我們看看下面的歸併排序圖。

我們已經把給定的清單分成兩半。這個列表不能被分成相等的部分,這一點都不重要。

歸併排序可以通過兩種方式實現——自頂向下和自底向上。我們在上面的例子中使用了自頂向下的方法,這是最常用的歸併排序。

自下而上的方法提供了更多的優化,我們將在後面定義。

算法的主要部分是我們如何組合兩個排序的子列表。讓我們合併兩個排序的合併列表。

  • A : [ 2 ,4,7,8]
  • B : [ 1 ,3,11]
  • 已排序:空

首先,我們觀察兩個列表的第一個元素。我們發現 B 的第一個元素更小,所以我們將它添加到我們的排序列表中,並在 B 列表中向前移動。

  • A : [ 2 ,4,7,8]
  • B : [1, 3 ,11]
  • 已排序:1

現在我們來看下一對元素 2 和 3。2 更小,所以我們將其添加到我們的排序列表中,並向前移動到列表中。

  • A : [ 2 ,4,7,8]
  • B : [1, 3 ,11]
  • 已排序:1

繼續這個過程,我們最終得到{1,2,3,4,7,8,11}的排序列表。可以有兩種特殊情況。

  • 如果兩個子列表都有相同的元素怎麼辦——在這種情況下,我們可以移動其中一個子列表,並將元素添加到排序列表中。從技術上講,我們可以在兩個子列表中前進,並將元素添加到排序列表中。
  • 我們在一個子列表中沒有剩餘的元素。當我們用完子列表中的時,只需一個接一個地添加第二個的元素。

我們應該記住,我們可以按照任何順序排序元素。我們按升序排序給定的列表,但我們可以很容易地按降序進行排序。

履行

歸併排序算法通過使用自頂向下的方法來實現。看起來可能有點困難,所以我們將詳細闡述每一步。在這裡,我們將在兩種類型的集合上實現這個算法——整數元素的列表(通常用於引入排序)和一個自定義對象(一個更實際和現實的場景)。

排序數組

算法的主要概念是將(子)列表分成兩半並遞歸排序。我們繼續這個過程,直到我們得到只有一個元素的列表。讓我們理解除法的以下功能-


def merge_sort(array, left_index, right_index): 
       if left_index >= right_index: 
                 return middle = (left_index + right_index)//2 
       merge_sort(array, left_index, middle) 
       merge_sort(array, middle + 1, right_index) 
       merge(array, left_index, right_index, middle) 

我們的主要重點是在排序發生之前將列表分成子部分。我們需要得到整數值,所以我們使用//運算符進行索引。

讓我們通過以下步驟來理解上述過程。

  • 第一步是創建列表的副本。第一個列表包含從【left _ index,…,中] 和第二個來自【中+1,?,右 _index] 。
  • 我們使用指針遍歷列表的兩個副本,選擇兩個值中較小的值,並將它們添加到排序列表中。一旦我們將元素添加到列表中,無論如何我們都會在排序列表中前進。
  • 將另一個副本中的剩餘元素添加到已排序的數組中。

讓我們在 Python 程序中實現歸併排序。

Python 程序


# funtion to divide the lists in the two sublists
def merge_sort(list1, left_index, right_index):
    if left_index >= right_index:
        return

    middle = (left_index + right_index)//2
    merge_sort(list1, left_index, middle)
    merge_sort(list1, middle + 1, right_index)
    merge(list1, left_index, right_index, middle)

    # Defining a function for merge the list
def merge(list1, left_index, right_index, middle):

   # Creating subparts of a lists
    left_sublist = list1[left_index:middle + 1]
    right_sublist = list1[middle+1:right_index+1]

    # Initial values for variables that we use to keep
    # track of where we are in each list1
    left_sublist_index = 0
    right_sublist_index = 0
    sorted_index = left_index

    # traverse both copies until we get run out one element
    while left_sublist_index < len(left_sublist) and right_sublist_index < len(right_sublist):

        # If our left_sublist has the smaller element, put it in the sorted
        # part and then move forward in left_sublist (by increasing the pointer)
        if left_sublist[left_sublist_index] <= right_sublist[right_sublist_index]:
            list1[sorted_index] = left_sublist[left_sublist_index]
            left_sublist_index = left_sublist_index + 1
        # Otherwise add it into the right sublist
        else:
            list1[sorted_index] = right_sublist[right_sublist_index]
            right_sublist_index = right_sublist_index + 1

        # move forward in the sorted part
        sorted_index = sorted_index + 1

    # we will go through the remaining elements and add them
    while left_sublist_index < len(left_sublist):
        list1[sorted_index] = left_sublist[left_sublist_index]
        left_sublist_index = left_sublist_index + 1
        sorted_index = sorted_index + 1

    while right_sublist_index < len(right_sublist):
        list1[sorted_index] = right_sublist[right_sublist_index]
        right_sublist_index = right_sublist_index + 1
        sorted_index = sorted_index + 1

list1 = [44, 65, 2, 3, 58, 14, 57, 23, 10, 1, 7, 74, 48]
merge_sort(list1, 0, len(list1) -1)
print(list1)

輸出:

[1, 2, 3, 7, 10, 14, 23, 44, 48, 57, 58, 65, 74]

對自定義對象排序

我們也可以使用 Python 類排序自定義對象。這個算法幾乎和上面的相似,但是我們需要使它更加通用,並通過比較函數。

我們將創建一個自定義類 Car,並向其中添加一些字段。我們對下面的算法做了一些修改,使其更加通用。我們可以通過使用 lambda 函數來做到這一點。

讓我們理解下面的例子。

Python 程序


class Car:
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year

    def __str__(self):
        return str.format("Make: {}, Model: {}, Year: {}", self.make, self.model, self.year)

def merge(list1, l, r, m, comp_fun):
    left_copy = list1[l:m + 1]
    r_sublist = list1[m+1:r+1]

    left_copy_index = 0
    r_sublist_index = 0
    sorted_index = l

    while left_copy_index < len(left_copy) and r_sublist_index < len(r_sublist):

        # We use the comp_fun instead of a simple comparison operator
        if comp_fun(left_copy[left_copy_index], r_sublist[r_sublist_index]):
            list1[sorted_index] = left_copy[left_copy_index]
            left_copy_index = left_copy_index + 1
        else:
            list1[sorted_index] = r_sublist[r_sublist_index]
            r_sublist_index = r_sublist_index + 1

        sorted_index = sorted_index + 1

    while left_copy_index < len(left_copy):
        list1[sorted_index] = left_copy[left_copy_index]
        left_copy_index = left_copy_index + 1
        sorted_index = sorted_index + 1

    while r_sublist_index < len(r_sublist):
        list1[sorted_index] = r_sublist[r_sublist_index]
        r_sublist_index = r_sublist_index + 1
        sorted_index = sorted_index + 1

def merge_sort(list1, l, r, comp_fun):
    if l >= r:
        return

    m = (l + r)//2
    merge_sort(list1, l, m, comp_fun)
    merge_sort(list1, m + 1, r, comp_fun)
    merge(list1, l, r, m, comp_fun)

car1 = Car("Renault", "33 Duster", 2001)
car2 = Car("Maruti", "Maruti Suzuki Dzire", 2015)
car3 = Car("Tata motor", "Jaguar", 2004)
car4 = Car("Cadillac", "Seville Sedan", 1995)

list1 = [car1, car2, car3, car4]

merge_sort(list1, 0, len(list1) -1, lambda carA, carB: carA.year < carB.year)

print("Cars sorted by year:")
for car in list1:
    print(car)

print()
merge_sort(list1, 0, len(list1) -1, lambda carA, carB: carA.make < carB.make)
print("Cars sorted by make:")
for car in list1:
    print(car)

輸出:

Cars sorted by year:
Make: Cadillac, Model: Seville Sedan, Year: 1995
Make: Renault, Model: 33 Duster, Year: 2001
Make: Tata motor, Model: Jaguar, Year: 2004
Make: Maruti, Model: Maruti Suzuki Dzire, Year: 2015

Cars sorted by make:
Make: Cadillac, Model: Seville Sedan, Year: 1995
Make: Maruti, Model: Maruti Suzuki Dzire, Year: 2015
Make: Renualt, Model: 33 Duster, Year: 2001
Make: Tata motor, Model: Jaguar, Year: 2004

最佳化

我們可以提高歸併排序算法的性能。首先讓我們了解自頂向下和自底向上歸併排序的區別。自底向上的方法迭代地排序相鄰列表的元素,其中自頂向下的方法將列表分成兩半。

給定的列表是[10,4,2,12,1,3],而不是將其分解為[10],[4],[2],[12],[1],[3] -我們將可能已經排序的子列表分成:[10,4],[2],[1,12],[3],現在準備排序它們。

對於較小的子列表,歸併排序在時間和空間上都是低效的算法。因此,對於較小的子列表,插入排序比歸併排序更有效。

結論

歸併排序是一種流行而有效的算法。這是一種更有效的大列表算法。它不依賴於任何導致壞運行時的不幸決定。

歸併排序有一個主要缺點。它使用額外的內存,用於在合併列表之前存儲列表的臨時副本。然而,歸併排序在軟件中被廣泛使用。它的性能是快速的,併產生出色的結果。

我們簡要討論了歸併排序概念,並通過用於比較的 lambda 函數在簡單整數列表和自定義對象上實現了它。


原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/254027.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-14 02:38
下一篇 2024-12-14 02:38

相關推薦

  • Python周杰倫代碼用法介紹

    本文將從多個方面對Python周杰倫代碼進行詳細的闡述。 一、代碼介紹 from urllib.request import urlopen from bs4 import Bea…

    編程 2025-04-29
  • Python中引入上一級目錄中函數

    Python中經常需要調用其他文件夾中的模塊或函數,其中一個常見的操作是引入上一級目錄中的函數。在此,我們將從多個角度詳細解釋如何在Python中引入上一級目錄的函數。 一、加入環…

    編程 2025-04-29
  • 如何查看Anaconda中Python路徑

    對Anaconda中Python路徑即conda環境的查看進行詳細的闡述。 一、使用命令行查看 1、在Windows系統中,可以使用命令提示符(cmd)或者Anaconda Pro…

    編程 2025-04-29
  • Python列表中負數的個數

    Python列表是一個有序的集合,可以存儲多個不同類型的元素。而負數是指小於0的整數。在Python列表中,我們想要找到負數的個數,可以通過以下幾個方面進行實現。 一、使用循環遍歷…

    編程 2025-04-29
  • Python計算陽曆日期對應周幾

    本文介紹如何通過Python計算任意陽曆日期對應周幾。 一、獲取日期 獲取日期可以通過Python內置的模塊datetime實現,示例代碼如下: from datetime imp…

    編程 2025-04-29
  • Python編程二級證書考試相關現已可以上網購買

    計算機二級Python考試是一項重要的國家級認證考試,也是Python編程的入門考試。與其他考試一樣,Python編程二級證書的考生需要進入正式考試,而為了備考,這篇文章將詳細介紹…

    編程 2025-04-29
  • Python清華鏡像下載

    Python清華鏡像是一個高質量的Python開發資源鏡像站,提供了Python及其相關的開發工具、框架和文檔的下載服務。本文將從以下幾個方面對Python清華鏡像下載進行詳細的闡…

    編程 2025-04-29
  • Python程序需要編譯才能執行

    Python 被廣泛應用於數據分析、人工智能、科學計算等領域,它的靈活性和簡單易學的性質使得越來越多的人喜歡使用 Python 進行編程。然而,在 Python 中程序執行的方式不…

    編程 2025-04-29
  • python強行終止程序快捷鍵

    本文將從多個方面對python強行終止程序快捷鍵進行詳細闡述,並提供相應代碼示例。 一、Ctrl+C快捷鍵 Ctrl+C快捷鍵是在終端中經常用來強行終止運行的程序。當你在終端中運行…

    編程 2025-04-29
  • 蝴蝶優化算法Python版

    蝴蝶優化算法是一種基於仿生學的優化算法,模仿自然界中的蝴蝶進行搜索。它可以應用於多個領域的優化問題,包括數學優化、工程問題、機器學習等。本文將從多個方面對蝴蝶優化算法Python版…

    編程 2025-04-29

發表回復

登錄後才能評論