改进的归并排序算法

来源:互联网 发布:unity2d横版rpg源码 编辑:程序博客网 时间:2024/05/21 17:44

归并排序的思想在于divide and conquer。一般的归并排序的时间复杂度为O(nlogn)。由于需要一个附加的同样长度的辅助空间,所以它的空间复杂度为O(n)。在conquer时,笔者尝试将插入排序的思想应用于归并的过程中,从而将归并排序的空间复杂度优化至O(1)。下面是普通归并排序的实现:

#include“iostream”

 

using namespace std;

 

void sort1(int *p1,int *p2,int left,int middle,int right)

{

    for(int i=left;i

        p2[i]=p1[i];

    int current1=left;

    int current2=middle;

    int a=left;

    while(current1

    {

        if(p2[current1]

            p1[a]=p2[current1++];

        else

            p1[a]=p2[current2++];

        a++;

    }

    if(current1==middle)

    {

        while(current2

         p1[a++]=p2[current2++];

    }

    else

    {

        while(current1

         p1[a++]=p2[current1++];

    }

}

 

void mergeSort(int *p1,int *p2,int left,int right)

{

    if(right>left+1)

    {

      int middle=(right+left)/2;

      mergeSort(p1,p2,left,middle);

      mergeSort(p1,p2,middle,right);

      sort1(p1,p2,left,middle,right);

    }

}

int main()

{

    int array1[20];

    int array2[20];

    for(int i=0;i<20;i++)

        cin>>array1[i];

    mergeSort(array1,array2,0,20);

    for(int i=0;i<20;i++)

        cout<<array1[i]<<"  ";

    return 0;

}

在优化时,主要将sort1函数修改即可。思想:在归并两个已排好序的序列L1和L2时,如果L1中的排序码小的话就原地不动,如果L2的排序码小,就把它放在L1上的相应位置。这样的话,就会覆盖了L1序列相应位置的排序码。解决的办法是,覆盖之前就先将其记录下来,然后通过插入排序的方法从L2起始位置开始插入L2序列中。这样便解决了覆盖问题并保证了L2序列的递增性。从这个算法来看,L2总是排好序的,这样的话遍历到L1的末尾就可以收工了。

附上代码:

#include“iostream”

#include“cstdlib”

 

using namespace std;

 

void sort1(int *p1,int left,int middle,int right)

{

    int current1=left;

    int current2=middle;

    while(current1

    {

        if(p1[current1]<=p1[current2])

           ;

        else

        {

          int m=p1[current1];

          p1[current1]=p1[current2];

          int c=current2+1;

          while(cp1[c])

          {

             p1[c-1]=p1[c];

             c++;

          }

          p1[c-1]=m;

        }

         current1++;

    }

}

 

void mergeSort(int *p1,int left,int right)

{

    if(right>left+1)

    {

      int middle=(right+left)/2;

      mergeSort(p1,left,middle);

      mergeSort(p1,middle,right);

      sort1(p1,left,middle,right);

    }

}

int main()

{

    int array1[200];

    for(int i=0;i<200;i++)

        array1[i]=rand()00;

    mergeSort(array1,0,200);

    for(int i=0;i<200;i++)

        cout<<array1[i]<<"  ";

    return 0;

}

PS:这种方法虽然降低了空间复杂度,但是在最坏的情况下(即如果给的是倒序时),算法的时间复杂度可以达到O(n*nlogn)。所以,可以通过事先随机化来打乱需要排序的序列,然后再进行改进后的归并排序。

0 0
原创粉丝点击