数组排序算法——归并排序(Merge)算法精讲及python实现

1. 归并排序算法思想

归并排序(Merge Sort)基本思想

采用经典的分治策略,先递归地将当前序列平均分成两半。然后将有序序列两两合并,最终合并成一个有序序列。

2. 归并排序算法步骤

  1. 分割过程:先递归地将当前序列平均分成两半,直到子序列长度为 1

    1. 找到序列中心位置 mid,从中心位置将序列分成左右两个子序列 left_arrright_arr

    2. 对左右两个子序列 left_arrright_arr 分别进行递归分割。

    3. 最终将数组分割为 n 个长度均为 1 的有序子序列。

  2. 归并过程:从长度为 1 的有序子序列开始,依次进行两两归并,直到合并成一个长度为 n 的有序序列。

    1. 使用数组变量 arr 存放归并后的有序数组。

    2. 使用两个指针 left_iright_i 分别指向两个有序子序列 left_arrright_arr 的开始位置。

    3. 比较两个指针指向的元素,将两个有序子序列中较小元素依次存入到结果数组 arr 中,并将指针移动到下一位置。

    4. 重复步骤 3,直到某一指针到达子序列末尾。

    5. 将另一个子序列中的剩余元素存入到结果数组 arr 中。

    6. 返回归并后的有序数组 arr

3. 归并排序动画演示

  1. 初始序列为 [6, 2, 1, 3, 7, 5, 4, 8]

  2. 将序列分解为 [6, 2, 1, 3][7, 5, 4, 8]

  3. 将序列分解为 [6, 2][1, 3][7, 5][4, 8]

  4. 将序列分为为 [6][2][1][3][7][5][4][8]

  5. 将序列看做是 8 个长度为 1 的子序列,即 [6][2][1][3][7][5][4][8]

  6. 1 趟排序:将子序列中的有序子序列两两归并,归并后的子序列为:[2, 6][1, 3][5, 7][4, 8]

  7. 2 趟排序:将子序列中的有序子序列两两归并,归并后的子序列为:[1, 2, 3, 6][4, 5, 7, 8]

  8. 3 趟排序:将子序列中的有序子序列两两归并,归并后的子序列为:[1, 2, 3, 4, 5, 6, 7, 8]。得到长度为 n 的有序序列,排序结束。

4. 归并排序算法分析

  • 时间复杂度:$O(n \times \log_2n)$。归并排序算法的时间复杂度等于归并趟数与每一趟归并的时间复杂度乘积。子算法 merge(left_arr, right_arr): 的时间复杂度是 $O(n)$,因此,归并排序算法总的时间复杂度为 $O(n \times \log_2 n)$。

  • 空间复杂度:$O(n)$。归并排序方法需要用到与参加排序的序列同样大小的辅助空间。因此算法的空间复杂度为 $O(n)$。

  • 排序稳定性:归并排序算法是一种 稳定排序算法

    • 因为在两个有序子序列的归并过程中,如果两个有序序列中出现相同元素,merge(left_arr, right_arr): 算法能够使前一个序列中那个相同元素先被复制,从而确保这两个元素的相对次序不发生改变。

5. 归并排序代码实现

class Solution:
    def merge(self, left_arr, right_arr):           # 归并过程
        arr = []
        left_i, right_i = 0, 0
        while left_i < len(left_arr) and right_i < len(right_arr):
            # 将两个有序子序列中较小元素依次插入到结果数组中
            if left_arr[left_i] < right_arr[right_i]:
                arr.append(left_arr[left_i])
                left_i += 1
            else:
                arr.append(right_arr[right_i])
                right_i += 1
        
        while left_i < len(left_arr):
            # 如果左子序列有剩余元素,则将其插入到结果数组中
            arr.append(left_arr[left_i])
            left_i += 1
            
        while right_i < len(right_arr):
            # 如果右子序列有剩余元素,则将其插入到结果数组中
            arr.append(right_arr[right_i])
            right_i += 1
        
        return arr                                  # 返回排好序的结果数组
 
    def mergeSort(self, arr):                       # 分割过程
        if len(arr) <= 1:                           # 数组元素个数小于等于 1 时,直接返回原数组
            return arr
        
        mid = len(arr) // 2                         # 将数组从中间位置分为左右两个数组。
        left_arr = self.mergeSort(arr[0: mid])      # 递归将左子序列进行分割和排序
        right_arr =  self.mergeSort(arr[mid:])      # 递归将右子序列进行分割和排序
        return self.merge(left_arr, right_arr)      # 把当前序列组中有序子序列逐层向上,进行两两合并。
 
    def sortArray(self, nums: List[int]) -> List[int]:
        return self.mergeSort(nums)
  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值