快速排序的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++快多了,就算封装成类还是要方便多=_=

快速排序的c++实现 和 python 实现

时间: 2024-10-11 18:28:03

快速排序的c++实现 和 python 实现的相关文章

快速排序,归并排序,堆排序python实现

快速排序的时间复杂度最好情况下为O(n*logn),最坏情况下为O(n^2),平均情况下为O(n*logn),是不稳定的排序 归并排序的时间复杂度最好情况下为O(n*logn),最坏情况下为O(n*logn),平均情况下为O(n*logn),是稳定的排序 堆排序的时间复杂度最好情况下为O(n*logn),最坏情况下为O(n*logn),平均情况下为O(n*logn),是不稳定的排序 1.快速排序 快速排序的介绍以及C语言实现在这里:快速排序C语言实现 本文介绍的是快速排序python实现: de

十大经典排序算法(python实现)(原创)

经典排序算法图解: 经典排序算法的复杂度: 大类一(比较排序法): 1.冒泡排序(Bubble Sort) python代码实现: 1 d0 = [2, 15, 5, 9, 7, 6, 4, 12, 5, 4, 2, 64, 5, 6, 4, 2, 3, 54, 45, 4, 44] 2 d0_out = [2, 2, 2, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 7, 9, 12, 15, 44, 45, 54, 64] # 正确排序 3 4 while 1: 5 stat

s11d27 算法

s11d27 算法 一.理论 1.1 时间复杂度和空间复杂度的理论: 1)空间复杂度: 是程序运行所以需要的额外消耗存储空间,一般的递归算法就要有o(n)的空间复杂度了, 简单说就是递归集算时通常是反复调用同一个方法,递归n次,就需要n个空间. 2)时间复杂度 一个算法花费的时间与算法中语句的执行次数成正比例,哪个算法中语句执行次数多,它花费时间就多. 算法的基本操作重复执行的次数是模块n的某一个函数f(n),因此,算法的时间复杂度记做:T(n)=O(f(n)). 随着模块n的增大,算法执行的时

快速排序——Python

快速排序: 在一组数据中选择一个基准值,让后将数据分为两个部分,一部分大于基准,一部分小于基准,然后按此方法将两个部分分组,直到不能再分为止. 需要明白一个概念递归和分而治之的概念. Python实现: 1 # 快速排序 2 3 import random 4 5 def quick_sort(arr): 6 # 边界条件 7 if len(arr) < 2: 8 return arr 9 key = random.choice(arr) # 选择基准 10 left = [i for i in

排序算法分析【六】:快速排序(附Python&amp;C++代码)

快速排序是由东尼·霍尔所发展的一种排序算法.在平均状况下,排序 n 个项目要Ο(n log n)次比较.在最坏状况下则需要Ο(n2)次比较. 算法原理 快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists). 步骤为: 从数列中挑出一个元素,称为 "基准"(pivot), 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边).在这个分区退出之后,该基准就处于数列的

快速排序算法回顾 --冒泡排序Bubble Sort和快速排序Quick Sort(Python实现)

冒泡排序的过程是首先将第一个记录的关键字和第二个记录的关键字进行比较,若为逆序,则将两个记录交换,然后比较第二个记录和第三个记录的关键字.以此类推,直至第n-1个记录和第n个记录的关键字进行过比较为止.上述过程称为第一趟冒泡排序,接着第二趟对前面n-1个关键字进行同样操作,…… 快速排序是对冒泡排序的一种改进,通过一趟排序将记录分割成独立的两部分,其中一部分记录的关键字均比另一部分关键字小,可分别对这两部分记录以递归的方法继续进行排序,以达到整个序列有序. 单趟Partition()函数过程请看

JavaScript 、Python Java、Go算法系列之【快速排序】篇

常见的内部排序算法有:插入排序.希尔排序.选择排序.冒泡排序.归并排序.快速排序.堆排序.基数排序等.用一张图概括: 选择排序 选择排序是一种简单直观的排序算法,无论什么数据进去都是O(n) 的时间复杂度.所以用到它的时候,数据规模越小越好.唯一的好处可能就是不占用额外的内存空间了吧.通俗来说就是你们中间谁最小谁就出列,站到队列的最后边,然后继续对着剩余的无序数组说你们中间谁最小谁就出列,站到队列的最后边,一直到最后一个,继续站到最后边,这样数组就有了顺序,从小到大. 1.算法步骤 a.首先在未

快速排序c++和python对比分析

C++的快速排序基本思想就是,任意取出一位作为对比位x,分别从序列两端开始探测,先从右边到左找到一个比x大的数,在从左边到右找到一个比x小的数,然后交换他们,一直循环到i=j.这一次交换完毕之后,将x换到中间位置,因为左边都比它小,右边都比它大,所以它在中间.在函数最后,有一个递归函数,分别在对左边和右边进行刚才的排序,直到将元素分解到1个的时候停止,循环结束. void quicksort(int left,int right) { int i,j,t,temp; if(left>right)

Python与快速排序

这个算法系列主要是自己学习算法过程中动手实践一下,写这个文章作为笔记和分享个人心得,如有错误请各位提出. 注:转载请说明出处 问题提出: 将以下数据升序排列:5, 2, 8, 6, 4, 9, 7, 3, 1 快速排序的原理: 快速排序的核心思想是(如下图) 1.先确定一个基准数,让后按照比较规则,如本例是升序排列,则将比基数大的放到右边,比基数小的放到左边. 2.接下来各边重复步骤1,直到全部排序完毕. 程序设计的思路就是(以上面的问题为例) 左右分别遍历比较 1 #非程序代码,只用来讲解 2