美文网首页
写给媳妇儿的算法(七)——归并排序

写给媳妇儿的算法(七)——归并排序

作者: 奔跑的徐胖子 | 来源:发表于2018-11-16 22:52 被阅读35次

归并排序是一个从思路到实现都极其的像快速排序的一个排序算法。同样,归并排序使用的思想也是 分治 思想,大事化小,小事化了

算法过程

回到我们的那个老问题,什么样的数列是绝对有序的?答案是空数列或者只含有一个数的数列是绝对有序的。归并排序就是先分解再合并,首先把数列通过二分的方式不停的进行分割,直到分割成所有的数列中的数都被拆开(这样没一个分出来的子数列就是绝对有序的),然后两两进行合并组成新的数列,再和其他的用同样方式组成的数列合并……直到最后,整个数列被合并为之前的数量,整个数列就排序完成。

如下图的上半部分,我们将原始数列经过几次的从中间拆分成两部分的操作,最终将数列 拆无可拆 ,变成了数列中所有的数都 “各自为战” ,这些各自为战的每一个数就是一个有序数列(就自己一个,当然是有序的)。

如下图的下半部分,我们将经过第一步拆分成各自为战的各个小的“数列”(单个的数)依次两两进行合并。这个过程就是将 两个有序数列 合并成 一个有序数列 的过程。合并到最后,并无可并 的时候,所有的数此时都被重新排列了,整个数列完成了排序,全部有序!

归并排序先分解再合并过程图.png

拆分的时候,比较容易拆分,我们合并的时候怎么合并呢?合并就是把两个有序数列合并成一个有序数列的过程。这个过程的具体操作如下图所示:

假设下图左侧的上下两个数列就是待合并的两个数列,右侧的数列就是合并之后的效果。右边的效果的合并过程,就如图中曲线中间的标号顺序:

  1. 设左侧上边数列为【1】,下边数列为【2】,右边的数列为合并后的新数列。(注意:【1】、【2】都是有序的)
  2. 比较【1】、【2】的第 1 个位置,2 < 7,因此,将【2】中的第一个数 2 移动到右边的新数列的第 1 个位置,【2】中的第 1 个数找到了归宿。
  3. 把还没有找到归宿的【2】的第 2 个数和【1】的第一个数比较,4 < 7, 因此将【2】中的第 2 个数 4 移动到右边新数列的第 2 个位置,【2】中的第 2 个数找到了归宿。
    ……
  4. 就是这样,【1】【2】中每找到一个数的归宿,就用这个数后面的数拿出来去比较,然后小的数移动到新的数列中。最终我们发现,其中一个数列会被 “搬空” ,就是我们这里的【2】。而【1】中还剩余两个数 10、12 。当出现 “搬空” 的时候,我们就把另外一个没被 “搬空” 的数列剩余的所有的数,原封不动的移动到新的数列的最后去。
  5. 最终我们发现,我们在这样的交叉=>比较=>后移=>比较中,把两个有序数列【1】、【2】合并成了一个新的有序数列。这就是合并两个有序数列为一个有序数列的方法。
合并两个有序数组的过程图.png

最终,通过先拆分,再合并,合并的过程中借助一个两两合并有序数列的方法,我们完成了最终的归并排序的全过程,我们的原始数列被排序完成!

算法实现

#coding:utf-8

import numpy as np 

# 归并排序
def merge_sort(data):
    merge_sort_content(data, 0, len(data)-1)

# 递归进行归并排序的实体部分
def merge_sort_content(data, f, t):
    if f >= t:
        return
    
    center = (f + t) // 2
    merge_sort_content(data, f, center)
    merge_sort_content(data, center+1, t)
    merge(data, f, center, t)

# 合并数组中的两部分
def merge(data, f, c, t):
    i = f
    j = c + 1
    temp = []

    # 把最小的依次放入临时数组中,此处需要额外开辟空间,所以归并排序不是就地排序,需要额外空间
    while i <= c and j <= t:
        if data[i] < data[j]:
            temp.append(data[i])
            i += 1
        else:
            temp.append(data[j])
            j += 1

    # 把没有挪完到临时数组的部分,挪到临时数组
    start = i 
    end = c
    if j <= t:
        start = j 
        end = t
    for k in range(start, end+1): # python的区间是左闭右开
        temp.append(data[k])

    # 把临时数组中的数,都拷贝回排序的区间上去
    data[f:t+1] = temp

array = np.arange(20)
np.random.shuffle(array)
array = list(array)
print('输入的数据: {}'.format(array))
merge_sort(array)
print('排序之后的数据:{}'.format(array))

结果是:

归并排序的结果.png



上一篇:写给媳妇儿的算法(六)——快速排序
下一篇:写个媳妇儿的算法(八)——桶排序

相关文章

  • 写给媳妇儿的算法(七)——归并排序

    归并排序是一个从思路到实现都极其的像快速排序的一个排序算法。同样,归并排序使用的思想也是 分治 思想,大事化小,小...

  • 2018-06-30

    排序算法之归并排序 归并排序算法是排序算法中的经典算法之一,其核心思想是利用归并的思想实现的排序方法,该算法采用经...

  • 排序算法之归并排序

    归并排序(Merge Sort) 归并排序是利用归并的思想实现排序的方式,该算法采用的是经典的分治算法 归并排序过...

  • java实现快速排序、归并排序、希尔排序、基数排序算法...

    快速排序算法 归并排序算法 希尔排序算法 基数排序算法

  • 归并排序

    图解排序算法(四)之归并排序 基本思想 归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用...

  • 归并排序

    归并排序 这个排序算法是建立在归并操作上的一种有效的排序算法,算法主要采用分治法,归并排序的算法复杂度为O(n*l...

  • 归并算法

    归并排序(Merge sort,台湾译作:合并排序)是建立在归并操作上的一种有效的排序算法。归并算法的中心是归并两...

  • 第三章:高级排序算法

    归并排序算法(mergeSort) 算法思想:Python使用函数实现: 自底向上的归并排序算法 算法思想:Pyt...

  • iOS - 归并排序

    Demo_github 归并排序: 归并排序(Merge Sort)是建立在归并操作上的一种有效的排序算法,算法主...

  • 归并排序

    归并排序 归并排序(Mergesort,台湾译作:合并排序)是建立在归并操作上的一种有效的排序算法。该算法是采用分...

网友评论

      本文标题:写给媳妇儿的算法(七)——归并排序

      本文链接:https://www.haomeiwen.com/subject/mcnlfqtx.html