您的位置:首页 > 其它

快速排序两种方式实现及优化总结

2016-09-26 20:01 841 查看
 今天看了快速排序,现在对自己的已知的方法进行总结,欢迎拍砖。

        快速排序被认为是20世纪十大算法之一,在排序中,快速排序其实就是我们前面认为最慢的冒泡排序的升级,它们都属于交换排序类。即快排也是通过不断比较和移动交换来实现排序的,不过它的实现,增大了记录的比较和移动的距离,将关键字较大的记录从前面直接移动到后面,关键字较小的从后面直接移动到前面,从而减少了总的比较次数和移动交换次数。

        在这里,我们假设对"6,1,2,7,9,3,4,5,10,8"这10个数进行排序。首先在这个序列中随便找一个数作为基准数,在这里为了方便,我们直接选取第一个数作为基准数,(在后面的优化中,会对基准数的选取做出优化),接下来需要将这个序列中所有比基准数大的数放在6的右边,基准数小的数放在6的左边,转变成这样:3
 1  2 5  4  6  9
7  10  8;接下来再对6左边和6右边的元素进行相同操作的递归。

 
      快排方法(一)和方法(二)在实现方式中有些差别,我们首先对于方法(一)的过程分析:

 
      首先分别对原始序列的两端进行探测,先从右往左找一个比6小的数,再从左向右找一个比6大的数,(在后面会说明为什么先要从6 的右边向左开始找)然后进行交换,直至当左向标等于右向标,然后将其共同指向的数与这轮的基准值进行交换,交换完毕后,分别从left到i-1的序列和从i+1到right进行递归,直至完全排序。

 
      NOTE:

 在实现快排方法(一)之前,我们先对快排一中为什么必须首先从右边开始向左边找做一个说明^_^

 
      如果我们在上述过程中,首先从左开始向右查找比6大的值,开始的左右互换不会出现问题,但是在最后与基准值交换就会出现问题!比如我们现在已经换到了这样的序列:6,1,2,7,9;此时若i从左向右进行查找, i到了7的位置会停下,j从右向左进行查找,j到了7的位置,和i相同,也会停下,这时6会与7进行交换,嘿嘿,这时7居然跑到了基准值6的右边!导致了结果错误,所以开始必须从右开始向左查找比基准值小的数。

     快排(一)实现具体如下:

#include <stdio.h>
int a[101],n;//定义全局变量,这两个变量需要在子函数中使用
void quicksort(int left,int right)
{
int i,j,t,temp;
if(left>right)
return;
temp=a[left]; //temp中存的就是基准数
i=left;
j=right;
while(i!=j)
{
//顺序很重要,要先从右边开始找
while(a[j]>=temp && i<j)
j--;
//再找右边的
while(a[i]<=temp && i<j)
i++;
//交换两个数在数组中的位置
if(i<j)
{
t=a[i];
a[i]=a[j];
a[j]=t;
}
}
//最终将基准数归位
a[left]=a[i];
a[i]=temp;
quicksort(left,i-1);//继续处理左边的,这里是一个递归的过程
quicksort(i+1,right);//继续处理右边的 ,这里是一个递归的过程
}
int main()
{
int i,j,t;
//读入数据
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
quicksort(1,n); //快速排序调用
//输出排序后的结果
for(i=1;i<=n;i++)
printf("%d ",a[i]);
getchar();getchar();
return 0;
}
    

下面我们来总结一下快排方法(二)的过程:

   快排方法二的总体其实和快排方法一是一样的,只是在循环条件和到每一轮最后中和基准值交换的时候有些不同。快排二是首先从左向右找出大值,接着再从右向左找出较小的值,(仔细想想与前面的顺序不同,接着是怎样来处理的)。因为快排方法一中的分析,我们可以了解到,如果是首先从左到右进行搜索时,会出现最后交换值的问题,为了避免交换值的问题,其中的一种思路是采用先从右向左搜索的方式,第二种思路则是依然是先从左到右搜索,但是在每一轮中跳出循环后,不是将左边left下标指向的值与基准值进行交换,而是将右边right下标指向的值与基准值进行交换,这样就可以避免最后在交换时出现最后将基准值换错的问题。

        快排(二)实现具体如下:

       
#include <stdio.h>
int a[101],n;//定义全局变量,这两个变量需要在子函数中使用
int Patition(int a[],int p,int r)
{
int i=p,j=r+1;
int tt;
int x = a[p];
while(true){
while(a[++i]<x&&i<r);
while(a[--j]>x);
if(i>=j) break;
tt=a[i];
a[i]=a[j];
a[j]=tt;
}
a[p] = a[j];
a[j] = x;
return j;
}
void QuickSort(int a[],int p,int r)
{
if(p<r){
int q = Patition(a,p,r);
QuickSort(a,p,q-1);
QuickSort(a,q+1,r);
}
}
int main(){
int i,j,t;
//读入数据
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
QuickSort(a,1,n); //快速排序调用
//输出排序后的结果
for(i=1;i<=n;i++)
printf("%d ",a[i]);
getchar();getchar();
return 0;
}


       快排的优化

       今天天色已晚,关于快排的优化,明天再做下总结  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: