归并排序

来源:互联网 发布:阿里云服务器个人备案 编辑:程序博客网 时间:2024/06/08 20:07

什么是归并排序??

归并排序的实现过程如图:



递归形式的代码如下所示:

#!/usr/bin/python#coding: utf-8def Merge_Sort(res):if len(res) <= 1:return resnum = len(res) // 2left = Merge_Sort(res[ : num])right = Merge_Sort(res[num : ])return Merge(left, right)def Merge(left, right):l, r = 0, 0result = []while l < len(left) and r < len(right):if left[l] < right[r]:result.append(left[l])l += 1else:result.append(right[r])r += 1result.extend(left[l : ])result.extend(right[r : ])return result if __name__ == "__main__":     result = [95, 45, 15, 78, 84, 51, 24, 12]      print Merge_Sort(result)    # result = [95, 45, 15, 78, 84, 51, 24, 12]      # print MergeSort(result)


归并排序在用递归实现的过程中,会产生很大的内存开销,可以通过迭代来实现归并排序,减小内存开销

归并排序的另一种实现方式:

对于一个给定的无序数组,把元素实行分组(其实就是在递归过程中的把列表每次平分的过程),开始的时候一个元素一组,然后每次扩大2倍,直到不能实行分组为止,循环结束。

假设分组的步长为i,n个元素,所以每一次分组以后分的组数为 n/i,每次取其中两组进行讨论,把这两组的元素从小到大排序。依次重复这个过程即可。

归并排序迭代实现的C++代码

#include <stdio.h>#include <stdlib.h>using namespace std;void Merge_Sort(int k[], int n){    // left_min 和 left_max 分别表示左边分组的最小值和最大值    // right_min 和 right_max 分别表示右边分组的最小值和最大值    int left_min, left_max, right_min, right_max;    // 开辟一个临时数组    int *temp = (int *)malloc(n * sizeof(int));    // i 为迭代的步长    for(int i = 1;i < n;i *= 2)    {        for(left_min = 0;left_min < n - i; left_min = right_max)        {            // 获取左边分组的最大值和最小值            right_min = left_max = left_min + i;            right_max = left_max + i;            // 每一次分组以后各个分组的元素个数可能和最后一个分组不相等,            // 所以要对最后一个分组进行讨论,防止越界            if(right_max > n)                right_max = n;            int next = 0; // 临时数组的下表            // 归并算法的两个分组元素的合并操作            while(left_min < left_max && right_min < right_max)            {                if(k[left_min] < k[right_min])                    temp[next ++] = k[left_min ++];                else                    temp[next ++] = k[right_min ++];            }            /*            注意:                当上面合并算法结束以后,可能会存在下面的两种情况                1. 左边的分组元素没有取完,右边的分组元素全部取完                    此时,要把左边部分没有取到的元素全部后移,放到k数组的结尾                2. 右边的分组元素没有取完,左边的分组元素全部取完                    此时, 不需要对没有取到的元素进行讨论,因为这些元素已经在 k 数组的结尾            */            // 右边的数据取完了,此时 right_min = right_max            // 对上面注意事项中的 1 进行实现            while(left_min < left_max)                k[-- right_min] = k[-- left_max];            //把 temp 临时数组的元素重新放入 k 数组中            // 如果说上面的 while 语句没有执行的话,则证明是注意事项中 2 的这种情况,只需要把temp数组中            // 当前的元素赋值给k数组即可,k数组后面没有变化的元素就是最开始while循环中右边分组没有取完的元素            while(next > 0)                k[-- right_min] = temp[-- next];        }    }}int main(){    int n = 10;    int a[11];    for(int i = 10;i >= 0;i --)        a[10 - i] = i;    printf("排序之前\n");    for(int i = 0;i < 10;i ++)        printf("%d ", a[i]);    printf("\n");    Merge_Sort(a, n);    printf("排序之后\n");    for(int i = 0;i < 10;i ++)        printf("%d ", a[i]);    printf("\n");    return 0;}


0 0
原创粉丝点击