关于快速排序中元素调整方法的分析

快速排序的相关资料网上有很多,基本的思路也比较简单:找一个基准值,将元素分成两部分,然后递归继续。

其中一直困扰我的一个点就是将元素分成两部分的问题,大部分文章都只讲方法,或者演示方法,但说实话我有点懵,因为我并没有搞清楚为什么这样那样做就能将元素调整为两部分,只是勉强记住了方法。

最近又碰到了这个问题,在网上查了很多资料,感觉终于搞清楚了,总结如下:

方法一:单向调整,最简单易懂

 1 /*单向调整,将元素按基准值分成三部分*/
 2 int pa(int a[],int left,int right)
 3 {
 4     /*为什么要按基准值分成三部分?
 5     如何分成两部分的话,某些情况会出现死循环
 6     例如将 2 3 4 5 3 分成两部分,得到的将是 |2 3 4 5 3 ,等于没分
 7     下次递归会导致 left与mid值相等,进入死循环*/
 8     
 9     int key=a[left];//选取基准值 
10     int t,i,j;
11     /*核心思路:让i左边的元素必须小于key,或者说让小于key的元素都在i左边
12       此循环将元素分成两部分:
13         a[left+1]~a[i-1]小于key,a[i]~a[right]大于等于key*/
14     for(i=j=left+1;j<=right;j++)
15     {    
16         if(a[j]<key)
17         {
18             t=a[i];a[i]=a[j];a[j]=t;
19             i++;
20         }
21     }
22     /*a[left]等于key,a[i-1]肯定小于key,交换后可以保证: 
23         i-1左边的元素小于key,i-1指向的元素等于key,i-1右边的元素大于等于key*/
24     t=a[i-1];a[i-1]=a[left];a[left]=t;
25     return i-1;
26 }

方法二:双向调整,其实只是对方法一的优化

/*双向调整1:参考单向调整的方法,将元素分成三部分*/ 
int pa(int a[],int left,int right)
{
    int i,j,t,key;
    key=a[left];
    i=left+1,j=right;
    while(i<=j)
    {
        //核心思路:让i左边的元素必须小于key,或者说让小于key的元素都在i左边 
        while(a[i]<key&&i<=j)i++;//循环后a[i]>=key  
        while(a[j]>=key&&i<=j)j--;//循环后a[j]<key
        //为什么要考虑i==j的情况?所有元素都小于key的情况下会出错 
        if(i<=j)
        {
            t=a[i];a[i]=a[j];a[j]=t;
            i++;j--;
        }
    }
    t=a[left];a[left]=a[i-1];a[i-1]=t;
    return i-1;
}
//sort()函数同上一个方法

方法三:双向调整,最常用的一种方法。

/*双向调整2:将元素分成 [i,right]、(j,i)、[left,j]三部分*/ 
void sort(int a[],int left,int right)
{
    int i,j,t,key;
    key=a[left];
    i=left,j=right;
    while(i<=j)//为什么要取等于?为了将元素分成三部分 
    {
        //让i左边元素小于key,循环后a[i]大于等于key 
        while(a[i]<key)i++;
        //让j右边元素大于key,循环后a[j]小于等于key 
        while(a[j]>key)j--;
        if(i<=j)
        {
            /*交换a[i] a[j]的值,i,j继续前进 
            因为交换,所以
            a[i]左边的元素实际上小于等于key
            a[j]右边的元素实际上大于等于key*/
            t=a[i];a[i]=a[j];a[j]=t;
            i++,j--;
        }
    }
    /*循环结束后j<i
        [i,right]的元素大于等于key,
        [left,j]的元素小于等于key
        (j,i)的元素等于key 
    */
    if(i<right)sort(a,i,right);
    if(left<j)sort(a,left,j);
} 

 

posted @ 2020-06-07 17:50  zbit  阅读(212)  评论(0编辑  收藏  举报