排序 6 - 归并排序

10 篇文章 0 订阅
10 篇文章 0 订阅

参考:

排序 0 - 前言

百度百科:归并排序


归并排序(merge sort)

工作原理

将序列分为若干个子序列(子序列均有序),两两子序列进行 归并操作,得到一个新的有序列表,最终归并所有子序列,得到一个递增或递减的序列

归并操作

从左到右逐个比较两个子序列中的元素大小,比如进行递增排序,将较小的元素加入结果序列中,其下标加 1,继续和另一个序列元素进行比较,直到某一个序列元素已经全部遍历为止,将另一个序列的剩余元素加入到结果序列中,操作完成

算法思想

对于无序列表,无法确切得知哪个子序列是有序的,可以将单个元素设为一个子序列,从而两两进行归并操作

归并排序通常采用递归算法,每次都将序列均分为两个子序列,直到序列数为 1,将两个子序列进行归并操作后返回


Python 算法实现

# -*- coding: utf-8 -*-

"""
归并排序
"""
import random

__author__ = 'zj'


def create_data(leng, min, max):
    """
    创建待排序序列
    :param leng: 序列长度
    :param min: 最小值
    :param max: 最大值
    :return: 列表
    """
    li = range(min, max)
    return random.sample(li, leng)


def merge_sort(li, reverse=False):
    """
    归并排序实现
    :param li: 待排序列表
    :param reverse: 是否从大到小排序,默认为False
    :return: 已排序列表
    """
    if len(li) == 1:
        return li
    m = len(li) // 2
    l = merge_sort(li[:m], reverse)
    r = merge_sort(li[m:], reverse)
    return merge_operation(l, r, reverse)


def merge_operation(llist, rlist, reverse=False):
    """
    归并操作实现
    :param llist: 左侧已排序序列
    :param rlist: 右侧已排序序列
    :param reverse: 是否从大到小排序,默认为False
    :return: 一个已排序序列
    """
    llen = len(llist)
    rlen = len(rlist)
    i = j = 0
    res = []
    while i < llen and j < rlen:
        if llist[i] <= rlist[j]:
            if reverse:
                res.append(rlist[j])
                j += 1
            else:
                res.append(llist[i])
                i += 1
        else:
            if reverse:
                res.append(llist[i])
                i += 1
            else:
                res.append(rlist[j])
                j += 1
    res.extend(llist[i:])
    res.extend(rlist[j:])
    return res


if __name__ == '__main__':
    da = create_data(10, 30, 60)
    print da
    res = merge_sort(da, True)
    print res

性能分析

稳定性

归并排序是稳定排序算法

其归并操作是发生在相邻两个子序列中,遇到相同大小的元素时,也是左侧的元素先加入结果序列中

时间复杂度

最好,最坏,平均时间复杂度均为 O(nlogn)

空间复杂度

每次归并操作均需要使用 n 个大小的辅助空间,所以空间复杂度为 O(n)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值