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

 今天看了快速排序,现在对自己的已知的方法进行总结,欢迎拍砖。

        快速排序被认为是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;
}


       快排的优化

       今天天色已晚,关于快排的优化,明天再做下总结  

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

精神抖擞王大鹏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值