4.6.2归并排序及其两种实现方式(详解)

4.6.2归并排序及其两种实现方式(详解)

原理:将序列两两分组,将序列归并为[n/2]个组,组内单独排序;排序后,将这些组再两两归并,生成[n/4]个组,组内单独排序,以此类推;直到只剩下一个组。时间复杂度为O(nlogn).

例子:{66,12,33,57,64,27,18}

先分成{66,12},{33,57},{64,27},{18},对它进行排序

{12,66},{33,57},{27,64},{18},

接着合并 并 排序

{12,33,57,66},{18,27,64}

最后把这两个也合并了

{12,18,27,33,57,64,66}.

归并排序有两种实现方法:

1.非递归

//归并排序 非递归
#include <cstdio>
#include <math.h>
#include <algorithm>
using namespace std;
const int maxn = 100;
int n = 10;
void mergesort(int a[]);
void merge(int a[],int l1, int r1, int l2,int r2);
//这是主函数
int main(void)
{
    int x[n] = {1,3,9,7,675,213,56,0,-10,13};
    mergesort(x);
    for(int i = 0 ; i < n ; i++)
    {
        printf("%d\n",x[i]);
    }
    return 0;
}
//利用c++ algorithm里的sort()
void mergesort(int a[])
{
    //step为组内元素的个数如2,4,8;step/2为左子区间元素个数
    for(int step = 2 ; step/2 < n ; step*=2)
    {
        //每step个元素一组,组内进行排序
        for( int j = 0 ; j < n ; j+=step)
        {
            sort(a + j, a + int(min(n ,j + step - 1)));
        }
    }
}


2.递归

//归并排序 递归
#include <cstdio>
#include <math.h>
#include <algorithm>
using namespace std;
const int maxn = 100;
int n = 10;
void mergesort(int a[],int left,int right);
void merge(int a[],int l1, int r1, int l2,int r2);
int main(void)
{
    int x[n] = {1,3,9,7,675,213,56,0,-10,13};
    mergesort(x,0,9);
    for(int i = 0 ; i < n ; i++)
    {
        printf("%d\n",x[i]);
    }
    return 0;
}
//将left 到 right之间的数据进行归并
void mergesort(int a[],int left,int right)
{
    if(left < right)//只要left < right,也就是区间长度>=2
    {
        int mid = (left + right)/2;
        mergesort(a,left,mid);//递归的算左子区间
        mergesort(a,mid + 1,right);//递归的算右子区间
        merge(a,left,mid,mid + 1,right);//把左子区间,右子区间合并并排序
    }
}
void merge(int a[],int l1 ,int r1 , int l2 ,int r2)
{
    int i = 0;
    int j=0;
    int k=0;
    int b[maxn] = {0};
    while(i + l1 <= r1 && j + l2 <= r2)//因为是其中一个放完,所以等号得取
    {
        if(a[l1 + i] < a[l2 + j])
        {
            b[k++] = a[l1 + i++];//把小的那个放入b中
        }
        else
        {
            b[k++] = a[l2 + j++];//把小的那个放入b中
        }
    }
//    printf("xxxx");
    while(i + l1 <= r1 ){ b[k++] = a[l1 + i++];}//把长的那个数组剩下的部分依次放入b中
    while(j + l2 <= r2 ){ b[k++] = a[l2 + j++];}
    for (int j = 0; j < k; j++) {
        a[l1 + j] = b[j];//把排序后的结果传给a
    }
}


猜你喜欢

转载自blog.csdn.net/J_aSON_/article/details/107784255
今日推荐