排序问题之归并排序

最近在看算法导论,一开始就讲了许多关于各种排序的问题,(原谅我之前只会STL模板库里的sort函数),正好oj上有一个简单排序题,如图:

 题意就是将序列排序然后找第k个数就行了,先随便交一发过了之后我觉得我应该学一些别的算法,于是这两天看懂了归并算法然后进行了实现。

归并排序

其实质就是分治,首先考虑下如何将左右两个有序数列合并。这个非常简单,只要从比较这两个数列的第一个数,谁小就先将他放入要排序的数列中。然后再进行比较,如果有数列为空,那直接将另一个数列的数据依次取出即可。

这个排序其实非常简单,让我们从小规模来看,当一个数组只有一个数的时候,显然他是有序的,当有两个数的时候,把这两个数分成两组,这两组各自都是有序的,然后将其合并,以此类推,通过不断地递归和合并,我们就能实现排序的目的了

合并的过程:

void merge(int arr[],int l,int mid,int r)   //我们将整个数组分为左部和右部,l为左部数组的起始点,mid作为两个数组的分割点,r为右部数组的结尾点,即两个数组分别为L[l....mid],R[mid+1.....r],这两个数组都是有序的
{
int llen=mid-l+1,rlen=r-mid; //两个数组的长度 int x[llen],y[rlen]; //新开辟两个的数组用来存放未排序的数据 for(int i=0;i<llen;i++) { x[i]=arr[l+i]; } for(int i=0;i<rlen;i++) { y[i]=arr[mid+1+i]; } int j=0,k=0; for(int i=l;i<=r;i++) { if(x[j]<=y[k]&&j<llen&&k<rlen) //谁小谁在前 { arr[i]=x[j++]; } else if(x[j]>y[k]&&j<llen&&k<rlen) { arr[i]=y[k++]; } else if(j>=llen) //谁先放完另一个数组接着依次放入 { arr[i]=y[k++]; } else if(k>=rlen) { arr[i]=x[j++]; } } }

ps:只声明一个数组也可以实现;

递归的函数:

变为子问题排序。

void mergesort(int arr[],int l,int r)
{
    if(l<r)
    {
        int mid=(l+r)/2;
        mergesort(arr,l,mid);        //分治,就是大数组从中间分成大小差不多的数组进行子问题的解决
        mergesort(arr,mid+1,r);
        merge(arr,l,mid,r);      //合并
    }
}

以下是该题代码:

#include<bits/stdc++.h>
using namespace std;
int a[10000005];
typedef long long ll;
void merge(int arr[],int l,int mid,int r)
{
    int llen=mid-l+1,rlen=r-mid;
    int x[llen],y[rlen];
    for(int i=0;i<llen;i++)
    {
        x[i]=arr[l+i];
    }
    for(int i=0;i<rlen;i++)
    {
        y[i]=arr[mid+1+i];
    }
    int j=0,k=0;
    for(int i=l;i<=r;i++)
    {
        if(x[j]<=y[k]&&j<llen&&k<rlen)
        {
            arr[i]=x[j++];
        }
        else if(x[j]>y[k]&&j<llen&&k<rlen)
        {
            arr[i]=y[k++];
        }
        else if(j>=llen)
        {
            arr[i]=y[k++];
        }
        else if(k>=rlen)
        {
            arr[i]=x[j++];
        }        
    }
} 
void mergesort(int arr[],int l,int r)
{
    if(l<r)
    {
        int mid=(l+r)/2;
        mergesort(arr,l,mid);
        mergesort(arr,mid+1,r);
        merge(arr,l,mid,r);
    }
}
int main()
{
    int n,k;
    cin>>n>>k;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
    }
    mergesort(a,0,n-1);
    /*for(int i=0;i<n;i++)
    {
        cout<<a[i]<<" ";
    }*/
    cout<<a[k-1]<<endl;
    return 0;
}

但是归并排序有一些缺陷,虽然和STL里的sort函数的复杂度均为O(nlogn),但是内存方面归并排序要占的很多,由此可见归并排序也并不是理想的排序方法,尤其是数据多的时候。之后会更新堆排序(前提是我先学会...

posted @ 2019-09-01 16:06  ~Monologue  阅读(2351)  评论(0编辑  收藏  举报