为何我决定以后都用快速排序


排序,看似很简单的问题,实则有大内容。我们人人都会玩扑克牌,而每次向牌堆摸牌插入手中时,无意间,我们已在排序。我们每摸出一张牌,都会按大小顺序把它放入合适的位置,即将这次摸来的牌插入手中首次比其大的牌之前。因而每次放完牌,我们手中的牌总是有序的。这种方法甚是简单,以至于我在这里说都怕被人笑话。但是,我们要庆幸的是幸好一副扑克牌只有54张,而不是5400,54000张。否则,你再这样排序试试。

简单的方法必然付出简单的代价,那就是耗时太严重。为此,总有一些人不满足简单耗时的方法,他们努力找出更加优越的排序算法。于是,折半插入排序,归并排序,堆排序,快速排序,应用而生。

这里,我主要来谈谈归并排序和快速排序。

所谓归并排序,就是将一个大序列的排序问题分解成为两个子序列的排序问题,然后对子序列递归使用同样的方式进行排序(直到每个子序列只有一个元素,自然有序了),在子序列排好序后,再将结果合并起来。

分解是很容易的,主要功夫就花在合并上了,也就是说归并排序的主要时间是花在归并上的。下面简单图示一个归并排序的流程。

 

下面看一下快速排序。快速排序其实就是先将任一元素作为杠杆点(通常是首元素),然后以杠杆点位分界,遍历待排元素,小的放左边,大的放右边。

再将左右各进行一次这样的排序,递归下去,直到所有元素均有序。

图示如下:

至于插入排序,归并排序,快速排序之间的差别,文字是很难描述的。因此,我们用程序来直观对比一下:

下面结果为随机产生的n个整数,然后分别利用插入排序,归并排序,快速排序对其排序进行时间(单位为秒)比较。运行结果:

时间为0并不代表不需要运行时间,只是时间很短,达不到一个时钟周期,就被忽略了。

从结果我们可以看出,数据量较小的情况下,集中排序效果相当,差别不明显。然而数据量达到数万数十万及以上,孰优孰劣便一目了然了。200000个数据排序是,插入排序简直不能忍,接近1分钟,不管你能不能接受,反正我是不能接受。

因此,我决定,以后只用快速排序。特别是数据量很大时,不要抱着插入排序不放了,其实冒泡排序亦然。所以,快速排序,名副其实的快,当然,归并排序也是相当不错的。

附上拙劣的源程序。不妥之处,望披露指正。xuyongjie1128@hotmail.com

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 

#include<iostream.h>
#include<stdlib.h>
#include<time.h>

void Insert_sort(int a[],int n)//插入排序
{
    int i,j,key;
    for(j=1;j<n;j++)
    {
        key=a[j];
        i=j-1;
        while(i>=0&&a[i]>key)
        {
            a[i+1]=a[i];
            i--;
        }
        a[i+1]=key;
    }
}

int Partition(int a[],int m,int n)//快速排序分解
{
    int x,i,j,temp;
    x=a[m];
    i=m;
    for(j=m+1;j<=n;j++)
    {
        if(a[j]<=x)
        {
            i=i+1;
            temp=a[i];
            a[i]=a[j];
            a[j]=temp;
        }
    }
    temp=a[i];
    a[i]=a[m];
    a[m]=temp;
    return i;
}

void QuickSort(int A[],int begin,int end)//快速排序
{
    int q;
    if(begin<end)
    {
        q=Partition(A,begin,end);
        QuickSort(A,begin,q-1);
        QuickSort(A,q+1,end);
    }
}


int *Union(int a[],int b[],int abegin,int aend,int bbegin,int bend)//归并
{
    int i=abegin,j=bbegin;
    int *c=new int[aend-abegin+1+bend-bbegin+1];
    while(i<=aend&&j<=bend)
    {
        if(a[i]<b[j])
        {
            c[i-abegin+j-bbegin]=a[i];
            i++;
        }
        else
        {
            c[i-abegin+j-bbegin]=b[j];
            j++;
        }
    }
    if(i>aend)
    {
        while(j<=bend)
        {
            c[i-abegin+j-bbegin]=b[j];
            j++;
        }
    }
    else
    {
        while(i<=aend)
        {
            c[i-abegin+j-bbegin]=a[i];
            i++;
        }
    }
    return c;
}

int *UnionSort(int a[],int begin,int end)//归并排序
{
    int q=(begin+end)/2;
    if(begin==end)
    {
        int *temp=&a[begin];
        return temp;
    }
    if(begin<end)
    {
        return Union(UnionSort(a,begin,q),UnionSort(a,q+1,end),0,q-begin,0,end-q-1);
    }
}

int *CreateRandomArry(int n)
{
    int *data=new int[n];
    int i;
    for(i=0;i<n;i++)
    {
        data[i]=rand();
    }
    return data;
}


void main()//主函数
{
    int i,n;
    time_t tstart,tend;
    while(true)
    {
        cout<<"\n输入待排序数个数:\n";
        cin>>n;
        if(n==0)
        {
            break;
        }
        int *data=CreateRandomArry(n);
        int *data2=new int[n];
        for(i=0;i<n;i++)
        {
            data2[i]=data[i];
        }

        long now=clock();
        Insert_sort(data,n);
        cout<<"插入排序时间:"<<double(clock()-now)/CLOCKS_PER_SEC<<endl;

        now=clock();
        int *result=UnionSort(data2,0,n-1);
        cout<<"归并排序时间:"<<double(clock()-now)/CLOCKS_PER_SEC<<endl;

        now=clock();
        QuickSort(data2,0,n-1);
        cout<<"快速排序时间:"<<double(clock()-now)/CLOCKS_PER_SEC<<endl;
    }
}

徐永杰

2013 年1月 18号

 

 

 

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM