排序算法之归并排序及其优化

归并排序


其他排序方法:选择排序冒泡排序归并排序快速排序插入排序希尔排序堆排序


思想

归并排序,顾名思义,两个有序的数组合并成一个有序的数组。只要数组的长度大于1,都可以先分为两个数组,并将这两个子数组排好序再合并。

性能

归并排序时稳定的排序算法,平均时间复杂度和最好最坏时间复杂度均为O(nlogn)。

代码

Python代码:

# 归并排序
# left为归并区域的第一个下标,right为归并区域的最后一个下标
def mergeSort(arr, left, right):
    if left >= right: return

    # 中间下标
    mid = left + right >> 1
    # 归并当前区域的左半边区域
    mergeSort(arr, left, mid)
    # 归并当前区域的右半边区域
    mergeSort(arr, mid + 1, right)
    # 合并左右两边区域并排序
    merge(arr, left, mid, right)


# 合并左右两边区域并排序
# left为左边区域的第一个下标,mid为左边区域的最后一个下标
# mid+1为右边区域的第一个下标,right为右边区域的最后一个下标
def merge(arr, left, mid, right):
    # 排序需要借助一个数组
    tmpArr = []
    i, j = left, mid + 1
    # 同时循环左右两个区域,小的数先移进tmpArr,直到其中一个区域没有数据
    while i <= mid and j <= right:
        if arr[i] <= arr[j]:
            tmpArr.append(arr[i])
            i += 1
        else:
            tmpArr.append(arr[j])
            j += 1
    # 若左边区域还有数据,则直接添加到后面
    while (i <= mid):
        tmpArr.append(arr[i])
        i += 1
    # 若右边区域还有数据,则直接添加到后面
    while (j <= right):
        tmpArr.append(arr[j])
        j += 1

    # 将合并排好序的数据复制到原数组
    for x in tmpArr:
        arr[left] = x
        left += 1

优化

我们会发现如果左右数组的数据刚好有序,那上述代码中,仍会将数据先复制到tmpArr,再复制回原数组。
只要在merge方法前加上下面的判断,就能使最好时间复杂度降为O(n):

# 右边区域的值全部比左边区域的值大时,则不需要进行合并排序
if arr[mid] <= arr[mid + 1]: return arr
# 归并排序
# left为归并区域的第一个下标,right为归并区域的最后一个下标
def mergeSort(arr, left, right):
    if left >= right: return

    # 中间下标
    mid = left + right >> 1
    # 归并当前区域的左半边区域
    mergeSort(arr, left, mid)
    # 归并当前区域的右半边区域
    mergeSort(arr, mid + 1, right)
    # 合并左右两边区域并排序
    merge(arr, left, mid, right)


# 合并左右两边区域并排序
# left为左边区域的第一个下标,mid为左边区域的最后一个下标
# mid+1为右边区域的第一个下标,right为右边区域的最后一个下标
def merge(arr, left, mid, right):
    # 右边区域的值全部比左边区域的值大时,则不需要进行合并排序
    if arr[mid] <= arr[mid + 1]: return arr

    # 排序需要借助一个数组
    tmpArr = []
    i, j = left, mid + 1
    # 同时循环左右两个区域,小的数先移进tmpArr,直到其中一个区域没有数据
    while i <= mid and j <= right:
        if arr[i] <= arr[j]:
            tmpArr.append(arr[i])
            i += 1
        else:
            tmpArr.append(arr[j])
            j += 1
    # 若左边区域还有数据,则直接添加到后面
    while (i <= mid):
        tmpArr.append(arr[i])
        i += 1
    # 若右边区域还有数据,则直接添加到后面
    while (j <= right):
        tmpArr.append(arr[j])
        j += 1

    # 将合并排好序的数据复制到原数组
    for x in tmpArr:
        arr[left] = x
        left += 1

其他排序方法:选择排序冒泡排序归并排序快速排序插入排序希尔排序堆排序

posted @ 2020-03-02 15:57  ccneko  阅读(577)  评论(0编辑  收藏  举报