zoukankan      html  css  js  c++  java
  • 快速排序的c++实现 和 python 实现

    最近在学python,其中有个要求实现快速排序的练习,就顺便复习了c++的快速排序实现。

    快速排序的基本思想是,通过一轮的排序将序列分割成独立的两部分,其中一部分序列的关键字(这里主要用值来表示)均比另一部分关键字小。继续对长度较短的序列进行同样的分割,最后到达整体有序。在排序过程中,由于已经分开的两部分的元素不需要进行比较,故减少了比较次数,降低了排序时间。

      详细描述:首先在要排序的序列 a 中选取一个中轴值,而后将序列分成两个部分,其中左边的部分 b 中的元素均小于或者等于 中轴值,右边的部分 c 的元素 均大于或者等于中轴值,而后通过递归调用快速排序的过程分别对两个部分进行排序,最后将两部分产生的结果合并即可得到最后的排序序列。

      “基准值”的选择有很多种方法。最简单的是使用第一个记录的关键字值。但是如果输入的数组是正序或者逆序的,就会将所有的记录分到“基准值”的一边。较好的方法是随机选取“基准值”,这样可以减少原始输入对排序造成的影响。但是随机选取“基准值”的开销大。

      为了实现一次划分,我们可以从数组(假定数据是存在数组中)的两端移动下标,必要时交换记录,直到数组两端的下标相遇为止。为此,我们附设两个指针(下角标)i 和 j, 通过 j 从当前序列的有段向左扫描,越过不小于基准值的记录。当遇到小于基准值的记录时,扫描停止。通过 i 从当前序列的左端向右扫描,越过小于基准值的记录。当遇到不小于基准值的记录时,扫描停止。交换两个方向扫描停止的记录 a[j] 与 a[i]。 然后,继续扫描,直至 i 与 j 相遇为止。扫描和交换的过程结束。这是 i 左边的记录的关键字值都小于基准值,右边的记录的关键字值都不小于基准值。

    快速排序示意图

    下面是实现代码和测试代码,使用了c++的模板函数,只有有实现operator <的类都可以排序:

    实现一:

    //快速排序练习c++实现
    //author:sixbeauty
    
    #include<iostream>
    #include<vector>
    #include<string>
    
    template<typename T>
    void swapData(std::vector<T> &p,int i,int j)	//交换向量中两个位置的值
    {
    	T data=p[i];	
    	p[i]=p[j];
    	p[j]=data;
    }
    
    template<typename T>
    void quickSort(std::vector<T> &p,int left,int right)	//快速排序实现函数
    {
    	if(left>=right)	return ;	//若右标志为小于或等于左标志位,则不作任何事
    
    	int	center=(left+right)/2;	//取中间数为key值
    	int	i=left,j=right;			//左、右游标定义
    
    	while(1)
    	{
    		while(p[i]<p[center])
    			i++;				//左游标移到第一个小于key值的位置
    		while(p[j]>p[center])	//右游标的移动
    			j--;
    
    		if(i==j)	break;		//i==j时,左、右游标i,j同时移动到key值的位置,排序完成
    
    		else if(i==center)
    		{
    			center=j;			//若左游标移动到key的位置而右游标未移动,交换i、j的值后,center也要改变
    		}
    
    		else if(j==center)
    		{
    			center=i;
    		}
    
    		swapData(p,i,j);		
    	}
    
    	quickSort(p,left,center-1);
    	quickSort(p,center+1,right);
    }
    
    int main()
    {
    	//测试代码
    	/*int p1[8]={1,4,5,7,11,2,18,9};
    	std::vector<int> vetInt;
    	for(int i=0;i<8;i++)
    		vetInt.push_back(p1[i]);
    
    	quickSort<int>(vetInt,0,7);
    
    	for(std::vector<int>::iterator itr=vetInt.begin();itr!=vetInt.end();itr++)
    		std::cout<<*itr<<",";
    	std::cout<<std::endl;*/
    
    
    	//测试代码
    	std::string p1[8]={"ba","a","abd","defef","c","ca","daaa","aaa"};
    	std::vector<std::string> vetStr;
    	for(int i=0;i<8;i++)
    		vetStr.push_back(p1[i]);
    
    	quickSort<std::string>(vetStr,0,7);
    
    	for(std::vector<std::string>::iterator itr=vetStr.begin();itr!=vetStr.end();itr++)
    		std::cout<<*itr<<",";
    	std::cout<<std::endl;
    }
    

      

    实现二:

      上面的实现是我按照以前教材上的逻辑做出来的,由于这个实现用了swap,多次的数值交换降低了效率,存在提升的空间,后来在网上看到一个更高效的版本,它选取数组第一位为key值。

    举例说明一下吧,这个可能不是太好理解。假设要排序的序列为

    2 2 4 9 3 6 7 1 5 首先用2当作基准,使用i j两个指针分别从两边进行扫描,把比2小的元素和比2大的元素分开。首先比较2和5,5比2大,j左移

    2 2 4 9 3 6 7 1 5 比较2和1,1小于2,所以把1放在2的位置

    2 1 4 9 3 6 7 1 5 比较2和4,4大于2,因此将4移动到后面

    2 1 4 9 3 6 7 4 5 比较2和7,2和6,2和3,2和9,全部大于2,满足条件,因此不变

    经过第一轮的快速排序,元素变为下面的样子

    [1] 2 [4 9 3 6 7 5]

    实现代码如下:

    template<typename T>
    void quickSort(std::vector<T> &p,int left,int right)	//快速排序实现函数
    {
    	if(left>=right)	return ;	//若右标志为小于或等于左标志位,则不作任何事
    
    	T keyData=p[left];			//选取第一位为key值
    	int	i=left,j=right;			//左、右游标定义
    
    	while(i<j)
    	{
    		while(i<j && p[j]>keyData)	//第一次进入循环,i=left,所以p[i]的值等于keyData,后面我们要保证p[i]=keyData
    			j--;				//右游标移动到第一个小于key值的位置,i<j保证不出界,防止下面的赋值出错
    
    		p[i]=p[j];				//这时p[j]的值等于keyData,但我们不马上赋值
    
    		while(i<j && p[i]<keyData)
    			i++;				
    
    		p[j]=p[i];				//经过这一轮后,p[i]的值又重新等于keyData
    	}	//跳出循环后,在i以前的值都小于keyData,在i以后的值都大于keyData,这时只要把keyData赋值给p[i]即可
    	p[i]=keyData;
         

    if(left<i)                      //这里必须加这个,不然在left是最小值的情况是死循环   quickSort(p,left,i-1); quickSort(p,i+1,right); }

      测试代码用上面的即可;

    实现三(python实现):

    python没有类模板,而且里面的所谓函数重载根本不能算重载嘛,整就一个c++里面的缺省参数(就多了个利用参数关键字赋值),不过python实现起来真的快很多,就忍了。

    下面是实现代码:

    #FileName: quckSort.py
    #author: sixbeauty
    
    def quickSort(p,left,right):
        if(left>=right):
            return
        keyData=p[left]
        i=left
        j=right
    
        while i<j:
            while (i<j and p[j]>keyData):
                j-=1
    
            p[i]=p[j]
    
            while (i<j and p[i]<keyData):
                i+=1
    
            p[j]=p[i]
    
        p[i]=keyData
    
        if(i>left):
            quickSort(p,left,i-1)
        quickSort(p,i+1,right)
    
    p=[8,4,5,7,11,2,9,19]
    quickSort(p,0,7)
    print(p)
    

      下次讨论python实现的压缩备份程序,python的实现比c++快多了,就算封装成类还是要方便多=_=

  • 相关阅读:
    Java实现 蓝桥杯VIP 算法训练 一元三次方程
    Java实现 蓝桥杯VIP 算法训练 乘法表
    Java实现 蓝桥杯VIP 算法训练 矩阵加法
    Java实现 蓝桥杯VIP 算法训练 一元三次方程
    Java实现 蓝桥杯VIP 算法训练 平方计算
    Java实现 蓝桥杯VIP 算法训练 平方计算
    Java实现 蓝桥杯VIP 算法训练 平方计算
    Java实现 蓝桥杯VIP 算法训练 乘法表
    Java实现 蓝桥杯VIP 算法训练 乘法表
    监管只是压倒网盘业务的一根稻草,但不是主要原因(答案只有一个:成本!)
  • 原文地址:https://www.cnblogs.com/sixbeauty/p/3816993.html
Copyright © 2011-2022 走看看