1
代码环境:python3.6

归并排序采用分治法,思想是:先递归拆分数组,再合并数组。

1、拆分数组

假设数组一共有 n 个元素,我们递归对数组进行折半拆分即n//2,直到每组只有一个元素为止。

2、合并数组

算法会从最小数组开始有序合并,这样合并出来的数组一直是有序的,所以合并两个有序数组是归并算法的核心,这里用两个简单数组示例:

  • 步骤1:新建一个空数组存放合并结果,用lr两个辅助指针记录两个数组当前操作位置;

image.png

  • 步骤2:从左到右逐一比较两个小数组中的元素,较小的元素先放入新数组,指针移位,直到lr指针超出尾部;

image.png

image.png

image.png

image.png

image.png

  • 步骤3:指针尚未移到尾部的数组,说明还有剩余元素,将剩余元素合并到新数组尾部。

image.png

算法实现

def merge(list_left, list_right):
    """
    入参数组都是有序的,此处将两个有序数组合并成一个大的有序数组
    """
    # 两个数组的起始下标
    l, r = 0, 0

    new_list = []
    while l < len(list_left) and r < len(list_right):
        if list_left[l] < list_right[r]:
            new_list.append(list_left[l])
            l += 1
        else:
            new_list.append(list_right[r])
            r += 1
    new_list += list_left[l:]
    new_list += list_right[r:]
    return new_list


def merge_sort(mylist):
    """归并排序
    mylist: 待排序数组
    return: 新数组list
    """
    if len(mylist) <= 1:
        return mylist

    mid = len(mylist) // 2
    list_left = merge_sort(mylist[:mid])
    list_right = merge_sort(mylist[mid:])
    return merge(list_left, list_right)


if __name__ == "__main__":
    mylist = [12, 33, 199, 0, 54, 33, 11]
    result = merge_sort(mylist)
    print(f'归并排序后:{result}')

算法效率

  • 时间复杂度:O(nlogn)

归并排序把数组一层层折半分组,长度为 n 的数组,折半层数就是 logn,每一层进行操作的运算量是 n,得出时间复杂度 O(nlogn)。

  • 空间复杂度:O(n)

每次归并操作需要创建额外的新数组,占用空间为 n,但这部分额外空间会随着方法的结束而释放,所以只需要算单次归并操作开辟的空间即可,得出空间复杂度 O(n)。

  • 稳定性:稳定

从算法中从左到右逐一比较,较小的先放入新数组,所以两个值相同的元素,排序后依然保持原先后顺序。

  • 非原地排序

oldk
3 声望2 粉丝