排序算法之快速排序

快速排序的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列

这个分割不一定是均等分割,意思就是,假如这个数组一共有16个元素,不一定是分割成8和8两个数组,也有可能是1和15两个数组。

设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。



#include<iostream>  
using namespace std;  
void QSort(int arr[],int begin,int end)  
{  
    //如果起始位置≥终点位置,那么就应该结束函数了  
    //因为在>的情况下,那是不合理;在=的情况下,只有一个元素,所以也不用排了  
    if(begin>=end)  
    {  
        return;  
    }  
    int first=begin,last=end;  
      
    //以11,4,7,8,43,2,56,23,8,1,3,9为例,介绍这个while   
    //这里是以第一个元素分分割点。  
    //目标是把比key小的都放在key的左边比key大的都放在key的右边  
      
    //整个快速排序算法,最最最重要,也是最最最难理解的地方就是这个while   
    int key=arr[first];  
    while(first<last)  
    {  
        //这个while的作用是从最右端开始,向左找,一直到有比arr[first]小的元素,然后停止   
        while(first<last&&arr[last]>=key)  
        {  
            last--;  
        }  
        //停止后,立马把从右到左第一个比key小元素赋给arr[first]   
        arr[first]=arr[last]; 
		         
        //这个while的作用是从最左端开始,向右找,一直到有比arr[first]大的元素,然后停止   
        while(first<last&&arr[first]<=key)  
        {  
            first++;  
        }  
        //停止后,立马把从左到到第一个比key大元素赋给arr[last]   
        arr[last]=arr[first];          
    }     
    arr[first]=key;
	
	//演示第一轮:原数组为11,4,7,8,43,2,56,23,8,1,3,9,key值为11,
	//从右往左,比较到9<11,此时last为11,arr[first]=arr[last], 所以9,4,7,8,43,2,56,23,8,1 ,3,9 
	//从左往右,比较到43>11,此时first为4,arr[last]=arr[first],所以9,4,7,8,43,2,56,23,8,1 ,3,43 
		
	//从右往左,比较到3<11,此时last为10,arr[first]=arr[last], 所以9,4,7,8,3 ,2,56,23,8,1 ,3,43 
	//从左往右,比较到56>11,此时first为6,arr[last]=arr[first],所以9,4,7,8,3 ,2,56,23,8,1 ,56,43 
		
	//从右往左,比较到1<11,此时last为9,arr[first]=arr[last],  所以9,4,7,8,3 ,2,1 ,23,8,1 ,56,43
	//从左往右,比较到23>11,此时first为7,arr[last]=arr[first],所以9,4,7,8,3 ,2,1 ,23,8,23,56,43
		
	//从右往左,比较到8<11,此时last为8,arr[first]=arr[last], 所以9,4,7,8,3 ,2,1 ,8 ,8,23,56,43
	//从左往右,比较到8<11,此时first为8,arr[last]=arr[first], 所以9,4,7,8,3 ,2,1 ,8 ,8,23,56,43
		
	//不满足 first<last, 所以跳出循环 
	//执行 arr[first]=key,所以9,4,7,8,3 ,2,1 ,8 ,11,23,56,43
      
    //上面的while循环完及执行完赋值语句之后,得到的效果是  
    //比arr[first]小的都排在它的左边, 比arr[first]大的都排在它的右边   
/*  for(int i=0;i<12;i++) 
    { 
       cout<<arr[i]<<" "; 
    } 
    cout<<endl; 
*/  
  
/*  原数组为 11,4,7,8,43,2,56,23,8,1,3,9 
    你可以把上面的输出语句的注释去掉,这样就可以得到很多行数据如下: 
    9 4 7 8 3 2 1 8 11 23 56 43     比11小的都排在它的左边, 比11大的都排在它的右边 
     
    8 4 7 8 3 2 1 9 11 23 56 43     对上一行数据key值11左边的数据也就是9 4 7 8 3 2 1 8进行排序,选择9为key值  
                                    比9小的都排在它的左边, 比9大的都排在它的右边,  
     
    1 4 7 8 3 2 8 9 11 23 56 43     对上一行数据key值9左边的数据也就是8 4 7 8 3 2 1进行排序,选择8为key值 
                                    比8小的都排在它的左边, 比8大的都排在它的右边 
                                    注意这里有点特殊,因为有两个8,所以可能会有读者觉得我上面那一句话不对, 
                                    要注意我说的8是 1 4 7 8 3 2 8 里最右边的那个8.  
                                    
    1 4 7 8 3 2 8 9 11 23 56 43     对上一行数据key值8左边的数据也就是1 4 7 8 3 2进行排序,选择1为key值 
                                    比1小的都排在它的左边, 比1大的都排在它的右边 
     
    1 2 3 4 8 7 8 9 11 23 56 43     本来应该对上一行数据key值1左边的数据进行比较的, 
                                    但可以看到1左边都没有数据,所以直接return了 。  
                                    这是对上一行数据key值1右边的数据也就是4 7 8 3 2进行排序,选择4为key值 
                                    比4小的都排在它的左边, 比4大的都排在它的右边 
     
    1 2 3 4 8 7 8 9 11 23 56 43     对上一行数据key值4右边的数据也就是1 2 3进行排序,选择1为key值 
                                    比1小的都排在它的左边, 比1大的都排在它的右边 
     
    1 2 3 4 7 8 8 9 11 23 56 43     对上一行数据key值1右边的数据也就是2 3进行排序,选择2为key值 
                                    比2小的都排在它的左边, 比2大的都排在它的右边 
     
    1 2 3 4 7 8 8 9 11 23 56 43      
     
    1 2 3 4 7 8 8 9 11 23 43 56     依次类推,大概能理解就行了  
     
*/   
    QSort(arr,begin,first-1);  
    QSort(arr,first+1,end);  
}  
  
int main(){  
    int arr[]={11,4,7,8,43,2,56,23,8,1,3,9};  
    int size = sizeof(arr)/sizeof(int);  
    QSort(arr,0,size-1);  
    for(int i=0;i<size;i++)  
    {  
       cout<<arr[i]<<" ";  
    }  
      
    return 0;  
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值