交换排序-经典的快速排序算法总结

时间复杂度,平均O(nlogn),最坏O(n);

不稳定的算法

1、算法思想

    快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod)。

(1) 分治法的基本思想

    分治法的基本思想是:将原问题分解为若干个规模更小但结构与原问题相似的子问题。递归地解这些子问题,然后将这些子问题的解组合为原问题的解。

(2)快速排序的基本思想

    设当前待排序的无序区为R[low..high],利用分治法可将快速排序的基本思想描述为:

①分解:

在R[low..high]中任选一个记录作为基准(Pivot),以此基准将当前无序区划分为左、右两个较小的子区间R[low..pivotpos-1)和R[pivotpos+1..high],并使左边子区间中所有记录的关键字均小于等于基准记录(不妨记为pivot)的关键字pivot.key,右边的子区间中所有记录的关键字均大于等于pivot.key,而基准记录pivot则位于正确的位置(pivotpos)上,它无须参加后续的排序。

注意:

    划分的关键是要求出基准记录所在的位置pivotpos。划分的结果可以简单地表示为(注意pivot=R[pivotpos]):

    R[low..pivotpos-1].keys≤R[pivotpos].key≤R[pivotpos+1..high].keys

                  其中low≤pivotpos≤high。

②求解:

通过递归调用快速排序对左、右子区间R[low..pivotpos-1]和R[pivotpos+1..high]快速排序。

③组合:

因为当"求解"步骤中的两个递归调用结束时,其左、右两个子区间已有序。对快速排序而言,"组合"步骤无须做什么,可看作是空操作。

1、如无序数组[3 2 4 1 5 9]

a),先把第一项[3]取出来,

用[3]依次与其余项进行比较,

如果比[3]小就放[3]前边,2 1 都比[3]小,所以全部放到[3]前边

如果比[3]大就放[3]后边,4 5 9比[3]大,放到[3]后边

一趟排完后变成下边这样:

排序前 3 2 4 1 5 9

排序后 2 1 3 4 5 9

b),对前半拉[2 1]继续进行快速排序

重复步骤a)【取第一项 2与其余项比较】后变成下边这样:

排序前 2 1

排序后 1 2

前半拉排序完成。

c),对后半拉[4 5 9]继续进行快速排序

重复步骤a)【取第一项 4与其余项比较】后变成下边这样:

排序前 4 5 9

排序后 4 5 9

d),对后半拉[5 9]继续进行快速排序

重复步骤a)【取第一项 5与其余项比较】后变成下边这样:

排序前 5 9

排序后 5 9

d在这个例子中可以忽略,但是当后面的数字较小时就得必不可少的循环继续下去。

前半拉排序完成。

总的排序也完成:

排序前:[3 2 4 1 5 9]

排序后:[1 2 3 4 5 9]

2、快速排序算法QuickSort

  void QuickSort(SeqList R,int low,int high)

   { //对R[low..high]快速排序

     int pivotpos; //划分后的基准记录的位置

     if(low<high){//仅当区间长度大于1时才须排序

        pivotpos=Partition(R,low,high); //对R[low..high]做划分

        QuickSort(R,low,pivotpos-1); //对左区间递归排序

        QuickSort(R,pivotpos+1,high); //对右区间递归排序

      }

    } //QuickSort

  注意:

    为排序整个文件,只须调用QuickSort(R,1,n)即可完成对R[l..n]的排序。

具体算法实现:

   1: int partition(int R[], int low, int high)
   2: {//对R[low..high]做划分
   3:     int pivot = R[low];
   4:     int tmp =0;
   5:  
   6: //    int i = low, j= high ;
   7: //    print(R+low,high-low+1);
   8:  
   9:     while(low < high)
  10:     {
  11:         while( low <high &&R[high] >= pivot)
  12:             --high ;
  13:         swap(R[low] ,R[high]);    
  14:  
  15:         while (low < high && R[low] <= pivot )
  16:             ++low;
  17:         swap(R[low] ,R[high]);        
  18:  
  19:         
  20:     }    
  21:  
  22:  
  23:     //print(R+i,j-i+1);
  24:     
  25:     return high;
  26: }
  27: void quick_sort_z(int R[] ,int low ,int high)
  28: { 
  29:     int pivot_pos; //划分后的基准记录的位置
  30:     if(low<high){  //仅当区间长度大于1时才须排序
  31:         pivot_pos = partition(R ,low, high); //对R[low..high]做划分
  32:     //    cout<<pivot_pos <<endl;
  33:         quick_sort_z(R, low, pivot_pos-1); //对左区间递归排序
  34:         quick_sort_z(R, pivot_pos+1, high);//对右区间递归排序
  35:     }
  36: }
  37:  
  38: void quick_sort(int R[], int low, int high)
  39: {
  40:     quick_sort_z(R,low,high);
  41: }

 

另一种partion算法实现:以最后一个元素作为基准

   1: int partition_a(int data[],int lo,int hi) 
   2: {
   3:     int key=data[hi];  //以最后一个元素,data[hi]为主元
   4:     int i=lo-1;
   5:     for(int j=lo;j<hi;j++)   ///注,j从p指向的是r-1,不是r。
   6:     {
   7:         if(data[j]<=key)
   8:         {
   9:             i=i+1;
  10:             swap(data[i],data[j]);
  11:         }
  12:     }
  13:     swap(data[i+1],data[hi]);   
  14:     return i+1;
  15: }

完整的源代码(VS2010编译):

   1: // code-summary.cpp : 定义控制台应用程序的入口点。
   2:  
   3: /**************************************************************************
   4:     * Copyright (c) 2013,  All rights reserved.
   5:     * 文件名称    : code-summary.cpp
   6:     * 文件标识    :
   7:     * 摘    要    : 快速排序算法
   8:     * 
   9:     * 当前版本    : Ver 1.0
  10:     * 作者    : 徐冬冬
  11:     * 完成日期    : 2013/05/10
  12:     *
  13:     * 取代版本    : 
  14:     * 原作者    :
  15:     * 完成日期    :  
  16:     * 开放版权  : GNU General Public License GPLv3
  17: *************************************************************************/
  18: #include "stdafx.h"
  19:  
  20: #include <iostream>
  21: #include <random>
  22: #include <stdlib.h>
  23: using namespace std;
  24:  
  25: //快速排序
  26:  
  27: void init(int a[], int len)
  28: {
  29:     int i =0;
  30:     for( i=0;  i<len ;i++)
  31:     {
  32:         a[i]= rand();
  33:     }
  34:     return ;    
  35: }
  36: void print(int *a, int len)
  37: {
  38:     int i =0;
  39:     for( i=0;  i<len; i++)
  40:     {
  41:         cout << a[i] <<'\t';
  42:     }
  43:     cout << endl;
  44:     return ;    
  45: }
  46: void swap(int &a, int &b)
  47: {
  48:     int tmp =a;
  49:     a = b;
  50:     b=tmp;
  51:     return ;
  52: }
  53: int partition(int R[], int low, int high)
  54: {//对R[low..high]做划分
  55:     int pivot = R[low];
  56:     int tmp =0;
  57:  
  58: //    int i = low, j= high ;
  59: //    print(R+low,high-low+1);
  60:  
  61:     while(low < high)
  62:     {
  63:         while( low <high &&R[high] >= pivot)
  64:             --high ;
  65:         swap(R[low] ,R[high]);    
  66:  
  67:         while (low < high && R[low] <= pivot )
  68:             ++low;
  69:         swap(R[low] ,R[high]);        
  70:  
  71:         
  72:     }    
  73:  
  74:  
  75:     //print(R+i,j-i+1);
  76:     
  77:     return high;
  78: }
  79:  
  80: int partition_a(int data[],int lo,int hi) 
  81: {
  82:     int key=data[hi];  //以最后一个元素,data[hi]为主元
  83:     int i=lo-1;
  84:     for(int j=lo;j<hi;j++)   ///注,j从p指向的是r-1,不是r。
  85:     {
  86:         if(data[j]<=key)
  87:         {
  88:             i=i+1;
  89:             swap(data[i],data[j]);
  90:         }
  91:     }
  92:     swap(data[i+1],data[hi]);   
  93:     return i+1;
  94: }
  95:  
  96: void quickSort(int R[] ,int low ,int high)
  97: { 
  98:     int pivot_pos; //划分后的基准记录的位置
  99:     if(low<high){  //仅当区间长度大于1时才须排序
 100:         pivot_pos = partition(R ,low, high); //对R[low..high]做划分
 101:     //    cout<<pivot_pos <<endl;
 102:         quickSort(R, low, pivot_pos-1); //对左区间递归排序
 103:         quickSort(R, pivot_pos+1, high);//对右区间递归排序
 104:     }
 105: }
 106:  
 107: void quickSort_a(int R[] ,int low ,int high)
 108: { 
 109:     int pivot_pos; //划分后的基准记录的位置
 110:     if(low<high){  //仅当区间长度大于1时才须排序
 111:         pivot_pos = partition_a(R ,low, high); //对R[low..high]做划分
 112:         //    cout<<pivot_pos <<endl;
 113:         quickSort_a(R, low, pivot_pos-1); //对左区间递归排序
 114:         quickSort_a(R, pivot_pos+1, high);//对右区间递归排序
 115:     }
 116: }
 117: void quick_sort(int R[], int low, int high)
 118: {
 119:     quickSort(R,low,high);
 120: }
 121:  
 122: void quick_sort_a(int R[], int low, int high)
 123: {
 124:     quickSort_a(R,low,high);
 125: }
 126:  
 127:  
 128: int _tmain(int argc, _TCHAR* argv[])
 129: {
 130:     int *arr = new int[10];
 131:     init(arr, 10);
 132:     print(arr, 10);
 133:     quick_sort(arr,0,9);
 134:     print(arr, 10 );
 135:  
 136:     init(arr, 10);
 137:     print(arr, 10);
 138:     quick_sort_a(arr,0,9);
 139:     print(arr, 10 );
 140:  
 141:     system("pause");
 142:     return 0;
 143: }
 144:  

 

 

参考资料:

http://student.zjzk.cn/course_ware/data_structure/web/paixu/paixu8.3.2.1.htm

http://www.cnblogs.com/kkun/archive/2011/11/23/2260270.html

http://blog.csdn.net/v_july_v/article/details/6262915

转载于:https://www.cnblogs.com/xuddong/archive/2013/05/10/3072160.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/461091.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c语言数组问题解析

#import <Foundation/Foundation.h>#define COUNT 10int main(int argc, const char * argv[]){//1、随机产生20个[10 , 50]的正整数存到数组中&#xff0c;并求数组中的所有元素最大值、最小值、平均值以及各元素之和。第二大值。// int max 0, min 0, sum 0, sec…

指针学习2

主要是指针数组、数组指针、函数指针的学习&#xff0c;以及二重指针、二维数组的学习。 一、指针数组与数组指针 1、概念 指针数组的实质是一个数组&#xff0c;这个数组中存储的内容全部是指针变量。数组指针的实质是一个指针&#xff0c;这个指针指向的是一个数组。2、分析…

php excel 分页,excel分页线怎么增加

增加excel分页线的方法&#xff1a;首先依次点击“工作簿视图-分页预览”&#xff1b;然后点击要在其下方插入分页符的这一行&#xff1b;最后在“页面布局”选项卡上的“页面设置”组中&#xff0c;单击“分隔符”即可。本文操作环境&#xff1a;Windows7系统&#xff0c;Micr…

C# 中的委托和事件

PDF 浏览&#xff1a;http://www.tracefact.net/Document/Delegates-and-Events-in-CSharp.pdf文中代码在VS2005下通过&#xff0c;由于VS2003(.Net Framework 1.1)不支持隐式的委托变量&#xff0c;所以如果在一个接受委托类型的位置直接赋予方法名&#xff0c;在VS2003下会报…

DEBUG、void、NULL、C库和API、临时匿名变量、main函数

一、程序调试的debug宏 1、程序调试的常见方案 单步调试、裸机LED调试、打印信息、log文件 利用调试器进行单步调试&#xff08;譬如IDE中&#xff0c;Jlink&#xff09;适用于新手&#xff0c;最大的好处就是直观&#xff0c;能够帮助找到问题。缺点是限制性大、速度慢。裸机…

php7 有ext skel吗,PHP扩展开发系列02 - 老司机起步之函数

上一篇扩展开发引导文章中。创建了编写扩展的三个基本文件。或许你会有个疑问PHP没有类似的自动生成项目框架的工具吗&#xff1f; 当然有。这篇文章就开始介绍使用 "php-ext-cli" 工具来生成扩展项目文件注意这里的 "php-ext-cli" 本身没有这玩意&#xf…

php 数据类型转换与比较

<?php define("PI", 3.1415926); echo PI."<br>"; //定义一个常量 define("GREETING","Hello world!");echo constant("GREETING")."<br>"; $a 10; $b "10a"; echo (string)$a $b; …

(转载)说说char

char一直都在使用并且大量的使用&#xff0c;但是&#xff0c;大部分都是在单一平台上&#xff0c;那样没有太多的问题&#xff0c;在windows上大量直接使用wchar_t来解决中文的问题。并且在使用跨平台时也大多直接使用了Qt的QString来节省了很多的麻烦&#xff0c;但是现在项目…

字符串类型、结构体、共用体、枚举、container宏、内存来源

一、C语言的字符串类型 1、C语言没有原生字符串类型 很多高级语言像java、C#等就有字符串类型&#xff0c;有个String来表示字符串&#xff0c;用法和int这些很像&#xff0c;可以String s1 "linux";来定义字符串类型的变量。C语言没有String类型&#xff0c;C语言…

WPF 正確理解ContentPresenter

2019独角兽企业重金招聘Python工程师标准>>> 我們先由下圖來看類層次,可知ContentControl繼承Control,ContentPresenter繼承FrameworkElement(Control也繼承FrameworkElement); 同樣的,ItemsControl繼承Control,ItemsPresenter繼承FrameworkElement. 在Control類並…

java 数据网格,easyui数据网格

easyui中的数据网格应用1.页面代码&#xff1a;class"java" name"code">String path request.getContextPath();String basePath request.getScheme()"://"request.getServerName()":"request.getServerPort()path"/";…

存储类、作用域、生命周期、链接属性

以下内容源于朱有鹏嵌入式课程的学习&#xff0c;如有侵权&#xff0c;请告知删除。 补充&#xff1a;https://blog.csdn.net/oqqHuTu12345678/article/details/71214255 一、概念集合 1、存储类 &#xff08;1&#xff09;存储类就是存储类型&#xff0c;也就是描述C语言变…

java动态交叉表,SqlServer如何生成动态交叉表查询

为了说明问题&#xff0c;我们用SqlServer自带的事例数据库(Northwind)来进行验证&#xff0c;所有的例子请放到Northwind中运行&#xff0c;我可能会省略Use语句&#xff0c;所引用的表&#xff0c;都是Northwind中的&#xff0c;下面我就不再说明了这里指的交叉表&#xff0c…

Canvas Clock

这两天在看html5的canvas,实现了上面那个东西 需要注意的地方&#xff1a; 1.canvas的sava()和restore()理解和使用 2.canvas的translate scale rotate ..的使用&#xff0c;每个变化都应该清楚圆心和角度..看&#xff1a;http://blog.sina.com.cn/s/blog_8fab526c01015tqs.htm…

CentOS 6.3 下用ntfs-3g挂载Windows NTFS分区

2019独角兽企业重金招聘Python工程师标准>>> 默认情况下&#xff0c;CentOS 6.3不支持Widows NTFS硬盘分区读写&#xff0c;要想把NTFS格式的磁盘挂载到CentOS 6.3下面需要安装第三方的插件ntfs-3g&#xff0c;这里我们采用编译安装插件。 1、安装编译器&#xff0c…

宏定义与预处理、函数和函数库

以下内容源于朱有鹏嵌入式课程的学习&#xff0c;如有侵权&#xff0c;请告知删除。 一、C语言预处理理论 1、由源码到可执行程序的过程 源码.c->(编译)->elf可执行程序源码.c->(编译)->目标文件.o->(链接)->elf可执行程序源码.c->(编译)->汇编文件.S…

PictureBox

代码添加图片&#xff1a; pictureBox1.Image Image.FromFile("F:\360wallpaper_dt.jpg"); http://msdn.microsoft.com/query/dev10.query?appIdDev10IDEF1&lZH-CN&kk(SYSTEM.WINDOWS.FORMS.PICTUREBOX);k(TargetFrameworkMoniker-%22.NETFRAMEWORK%2cVERS…

C++的const修饰

2019独角兽企业重金招聘Python工程师标准>>> C的const修饰 ‍const的两个用途‍ &#xff08;1&#xff09;可以定义 const 常量 &#xff08;2&#xff09;const 可以修饰函数的参数、返回值. const的好处 &#xff08;1&#xff09;便于进行类型检查&#xff0c;…

链表(单链表、双链表、内核链表)

以下内容源于朱有鹏嵌入式课程的学习&#xff0c;如有侵权&#xff0c;请告知删除。 一、链表的引入 1、从数组的缺陷说起 数组有2个缺陷&#xff0c;一个是数组中所有元素的类型必须一致&#xff1b;第二个是数组的元素个数必须事先制定并且一旦指定之后不能更改。数组的第一…

心率变异性 matlab,心率变异性好的功率谱分析方面的问题

本帖最后由 天路 于 2018-2-25 21:16 编辑本人正在学习心率变异性方面的内容&#xff0c;但是按照文献上的方法做出来的结果并不是很理想&#xff0c;文献上说的是心率变异性的频率的范围是0.4以内&#xff0c;但是我做的功率谱上显示频率分布在整个频域内&#xff0c;试了很多…