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

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

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

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

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

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

实现一:

  1. //快速排序练习c++实现
  2. //author:sixbeauty
  3.  
  4. #include<iostream>
  5. #include<vector>
  6. #include<string>
  7.  
  8. template<typename T>
  9. void swapData(std::vector<T> &p,int i,int j) //交换向量中两个位置的值
  10. {
  11. T data=p[i];
  12. p[i]=p[j];
  13. p[j]=data;
  14. }
  15.  
  16. template<typename T>
  17. void quickSort(std::vector<T> &p,int left,int right) //快速排序实现函数
  18. {
  19. if(left>=right) return ; //若右标志为小于或等于左标志位,则不作任何事
  20.  
  21. int center=(left+right)/2; //取中间数为key值
  22. int i=left,j=right; //左、右游标定义
  23.  
  24. while(1)
  25. {
  26. while(p[i]<p[center])
  27. i++; //左游标移到第一个小于key值的位置
  28. while(p[j]>p[center]) //右游标的移动
  29. j--;
  30.  
  31. if(i==j) break; //i==j时,左、右游标i,j同时移动到key值的位置,排序完成
  32.  
  33. else if(i==center)
  34. {
  35. center=j; //若左游标移动到key的位置而右游标未移动,交换i、j的值后,center也要改变
  36. }
  37.  
  38. else if(j==center)
  39. {
  40. center=i;
  41. }
  42.  
  43. swapData(p,i,j);
  44. }
  45.  
  46. quickSort(p,left,center-1);
  47. quickSort(p,center+1,right);
  48. }
  49.  
  50. int main()
  51. {
  52. //测试代码
  53. /*int p1[8]={1,4,5,7,11,2,18,9};
  54. std::vector<int> vetInt;
  55. for(int i=0;i<8;i++)
  56. vetInt.push_back(p1[i]);
  57.  
  58. quickSort<int>(vetInt,0,7);
  59.  
  60. for(std::vector<int>::iterator itr=vetInt.begin();itr!=vetInt.end();itr++)
  61. std::cout<<*itr<<",";
  62. std::cout<<std::endl;*/
  63.  
  64. //测试代码
  65. std::string p1[8]={"ba","a","abd","defef","c","ca","daaa","aaa"};
  66. std::vector<std::string> vetStr;
  67. for(int i=0;i<8;i++)
  68. vetStr.push_back(p1[i]);
  69.  
  70. quickSort<std::string>(vetStr,0,7);
  71.  
  72. for(std::vector<std::string>::iterator itr=vetStr.begin();itr!=vetStr.end();itr++)
  73. std::cout<<*itr<<",";
  74. std::cout<<std::endl;
  75. }

  

实现二:

  上面的实现是我按照以前教材上的逻辑做出来的,由于这个实现用了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]

实现代码如下:

  1. template<typename T>
  2. void quickSort(std::vector<T> &p,int left,int right) //快速排序实现函数
  3. {
  4. if(left>=right) return ; //若右标志为小于或等于左标志位,则不作任何事
  5.  
  6. T keyData=p[left]; //选取第一位为key值
  7. int i=left,j=right; //左、右游标定义
  8.  
  9. while(i<j)
  10. {
  11. while(i<j && p[j]>keyData) //第一次进入循环,i=left,所以p[i]的值等于keyData,后面我们要保证p[i]=keyData
  12. j--; //右游标移动到第一个小于key值的位置,i<j保证不出界,防止下面的赋值出错
  13.  
  14. p[i]=p[j]; //这时p[j]的值等于keyData,但我们不马上赋值
  15.  
  16. while(i<j && p[i]<keyData)
  17. i++;
  18.  
  19. p[j]=p[i]; //经过这一轮后,p[i]的值又重新等于keyData
  20. } //跳出循环后,在i以前的值都小于keyData,在i以后的值都大于keyData,这时只要把keyData赋值给p[i]即可
  21. p[i]=keyData;
  22.     
  23.  
  24. if(left<i)                      //这里必须加这个,不然在left是最小值的情况是死循环
  25.   quickSort(p,left,i-1);
  26. quickSort(p,i+1,right);
  27. }

  测试代码用上面的即可;

实现三(python实现):

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

下面是实现代码:

  1. #FileName: quckSort.py
  2. #author: sixbeauty
  3.  
  4. def quickSort(p,left,right):
  5. if(left>=right):
  6. return
  7. keyData=p[left]
  8. i=left
  9. j=right
  10.  
  11. while i<j:
  12. while (i<j and p[j]>keyData):
  13. j-=1
  14.  
  15. p[i]=p[j]
  16.  
  17. while (i<j and p[i]<keyData):
  18. i+=1
  19.  
  20. p[j]=p[i]
  21.  
  22. p[i]=keyData
  23.  
  24. if(i>left):
  25. quickSort(p,left,i-1)
  26. quickSort(p,i+1,right)
  27.  
  28. p=[8,4,5,7,11,2,9,19]
  29. quickSort(p,0,7)
  30. print(p)

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

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

  1. $用python实现快速排序算法

    本文主要介绍用python实现基本的快速排序算法,体会一下python的快排代码可以写得多么简洁. 1. 三言两语概括算法核心思想 先从待排序的数组中找出一个数作为基准数(取第一个数即可),然后将原来 ...

  2. s11d27 算法

    s11d27 算法 一.理论 1.1 时间复杂度和空间复杂度的理论: 1)空间复杂度: 是程序运行所以需要的额外消耗存储空间,一般的递归算法就要有o(n)的空间复杂度了, 简单说就是递归集算时通常是反 ...

  3. 快速排序(python实现)

    算法导论上的快速排序采用分治算法,步骤如下: 1.选取一个数字作为基准,可选取末位数字 2.将数列第一位开始,依次与此数字比较,如果小于此数,将小数交换到左边,最后达到小于基准数的在左边,大于基准数的 ...

  4. python 实现冒泡排序与快速排序 遇到的错误与问题

    今天看了兄弟连php里面的冒泡排序与快速排序,想了下应该可以用python实现. 冒泡排序函数: def mysort(x): len1 = len(x) for i in range(len1-1, ...

  5. 你需要知道的九大排序算法【Python实现】之快速排序

    五.快速排序 基本思想:  通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分关键字小,则分别对这两部分继续进行排序,直到整个序列有序. 算法实现: ​ #coding: ...

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

    冒泡排序的过程是首先将第一个记录的关键字和第二个记录的关键字进行比较,若为逆序,则将两个记录交换,然后比较第二个记录和第三个记录的关键字.以此类推,直至第n-1个记录和第n个记录的关键字进行过比较为止 ...

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

    常见的内部排序算法有:插入排序.希尔排序.选择排序.冒泡排序.归并排序.快速排序.堆排序.基数排序等. 用一张图概括: 选择排序 选择排序是一种简单直观的排序算法,无论什么数据进去都是 O(n²) 的 ...

  8. Python之排序算法:快速排序与冒泡排序

    Python之排序算法:快速排序与冒泡排序 转载请注明源地址:http://www.cnblogs.com/funnyzpc/p/7828610.html 入坑(简称IT)这一行也有些年头了,但自老师 ...

  9. python实现快速排序

    最近在公司的工作内容发生变化,短期内工作量变少了,这也让我有时间整理一些日常学习和工作中的收获或思路.所以申请了博客,并打算持续更新. 快速排序采用了分治的思想,基本思想是选取数组中一个数为基准数(一 ...

随机推荐

  1. 将QQl里面的休息都迁移过来了

    以前一直在QQ空间里面写,今天把以前工作的,积累的都搬到博客园了,这才是一个很好交流的平台!

  2. (剑指Offer)面试题37:两个链表的第一个公共结点

    题目: 输入两个链表,找出它们的第一个公共结点. 链表结点的定义如下: struct ListNode{ int val; ListNode* next; ListNode(int x):val(x) ...

  3. AutoCAD .NET二次开发(二)

    今天专门讲一个--CommandMethod.我们都在知道CAD操作要快,必须要熟悉掌握各种命令.在Lisp开发中,在函数后C:即可添加一个命令,非常方法,在.NET API也可以非常方便的设置命令, ...

  4. iOS NSFileManager对沙盒文件及目录添加删除操作

    iOS 使用 NSFileManager对沙盒里面的文件和目录,增加,修改,删除操作: - (void)viewDidLoad { [super viewDidLoad]; self.title = ...

  5. 安装Vagrant出错 安装Homestead出错失败

    安装Vagrant出错 安装Homestead出错     我们也可以在电脑上创建其它文件夹,只需保证创建的文件夹路径跟 Homestead.yaml 文件中的 folders - map 保持一致即 ...

  6. Choose which tree,form view in many2one

    <field name="partner_id" context="{'ref_form_view': 'view_id_of_my_form','ref_tree ...

  7. 十五套专为开发人员打造的PHP资源库

    转载自:http://developer.51cto.com/art/201508/488143.htm 1)Mink Mink是一套PHP 5.3库,用于在测试当中模拟Web应用程序与浏览器之间的交 ...

  8. java.lang.ClassNotFoundException: org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter /struts2.1.3以前版本和之后版本区别/新版Eclipse找不到Java EE Module Dependencies选项

    严重: Exception starting filter struts2java.lang.ClassNotFoundException: org.apache.struts2.dispatcher ...

  9. 点击button触发onclick事件判空后依旧自动跳转

    这是一个前端的问题. 其中判断字符串为空的脚本代码是这样的: var remark = $("#Remark").val(); //判空.注意:var reg = /空格/g; v ...

  10. Excel小笔记——冻结窗格

    excel提供了冻结首行首列功能 但是, 大部分时间我们是希望 冻结多行窗格 方法:选中要冻结多行窗格的下一行,点击视图——冻结拆分窗格