C语言快速排序算法及三种优化方式

  • C语言快速排序算法及三种优化方式

    • 原理
    • 快速排序复杂度分析
      • 1 时间复杂度
      • 2 空间复杂度
    • 快速排序代码实现
      • 1 普通快速排序
      • 2 快速排序优化1-三数取中优化不必要的交换
      • 3 快速排序优化2-优化递归操作
      • 4 快速排序优化3-优化小数组时的排序方案

1. 原理

快速排序的基本思想就是从一个数组中任意挑选一个元素(通常来说会选择最左边的元素)作为中轴元素,将剩下的元素以中轴元素作为比较的标准,将小于等于中轴元素的放到中轴元素的左边,将大于中轴元素的放到中轴元素的右边,然后以当前中轴元素的位置为界,将左半部分子数组和右半部分子数组看成两个新的数组,重复上述操作,直到子数组的元素个数小于等于1。


2. 快速排序复杂度分析

2.1 时间复杂度

  • 在最好情况下,快速排序算法的时间复杂度为O(nlogn)
  • 在最坏情况下,待排序的序列为正序或者逆序,每次划分只得到一个臂上次划分少一个记录的子序列,而且另一个序列还为空。如果递归树画出来,它就是一棵斜树。此时需要执行(n-1)次递归调用,且第i次划分需要经过i-1次关键字的比较才能找到第i个记录,即中轴元素的位置,因此比较次数为:n-1+n-2+n-3+…+1 = n*(n-1)/2 时间复杂度为O(n^2)

2.2 空间复杂度

  • 在最好情况下,递归树的深度为logn,其时间复杂度为O(logn)
  • 在最坏情况下,需要进行n-1次递归调用,其空间复杂度为O(n)

3. 快速排序代码实现

3.1 普通快速排序

普通快速排序代码如下

/***************************
Author:tmw
date:2017-11-5
*************************/
#include <stdio.h>
#include <stdlib.h>/**普通快速排序**/
//选取序列中的第一个元素作为中轴元素
int first_ele_fast_sort( int array[] , int low , int high )
{int target = array[low];//选取最左边元素为中轴while( low < high ){while( low < high && array[high] >= target )high--;//high为数组最右边下标//交换int temp;temp = array[high];array[high] = array[low];//当前low的位置存的是target值array[low] = temp;while( low < high && array[low] <= target )low++;//交换temp = array[low];array[low] = array[high];//经上一轮交换,当前high位置存的是target值array[high] = temp;}return low;//返回当前中轴元素下标值
}int* first_ele_fast_sort_all( int array[] , int low , int high )//这里的high为array_len-1
{if( low < high ){int target_index;target_index = first_ele_fast_sort(array,0,high);//数组元素从0下标开始存first_ele_fast_sort(array,0,target_index-1);//对中轴元素左边快排first_ele_fast_sort(array,target_index+1,high);//对中轴元素的右边快排}return array;
}

3.2 快速排序优化1—-三数取中&&优化不必要的交换

优化点:
优化选取中轴元素

以上代码target 选取的位置是认定了数组元素的首位,但是若这个数值的大小不在整个数组的中间位置,会大大降低快排的性能。target = array[low] 这句就成了一个潜在的性能瓶颈。因此快速排序的速度还取决于这个target关键元素在数组中的位置。
【改进方法】
三数取中法:去三个元素先进行排序,将中间数作为中轴元素,下面的代码选取数组的左、中、右三个数;

优化交换

将上一个代码中的交换改成直接赋值,减少了多次交换数据的操作,在性能上又得到了部分提高

优化1的快速排序代码如下:

/*************************
Author:tmw
date:2017-11-5
**************************/#include <stdio.h>
#include <stdlib.h>
/**快速排序优化----三数取中&&优化不必要的交换**/
//取三个元素先进行排序,将中间值作为中轴元素,选取左端、右端、中间三个数,也可以随机选取
int Three_choose_one_optimize_fastSort( int array[] , int low , int high )
{int mid = ( low + high ) / 2;if( array[high] < array[low] ){int temp1;temp1 = array[high];array[high] = array[low];array[low] = temp1;}if( array[high] < array[mid] ){int temp2;temp2 = array[high];array[high] = array[mid];array[mid] = temp2;}//以上,保证high为三个值当中最大值的下标if( array[mid] > array[low] )//将low作为中间值的下标{int temp3;temp3 = array[low];array[low] = array[mid];array[mid] = temp3;}//以上,完成了三数取中,此时array[low]即可作为快排优化后的中轴元素int target = 0;target = array[low];while( low < high ){while( low < high && array[high] >= target  )high--;array[low] = array[high];//此时high位置上的元素为待处理元素while( low < high && array[low] <= target   )low++;array[high] = array[low];//将大于target值的元素放到待处理的high位置上,那么此时,low位置变为待处理}array[low] = target; //以上,省去交换,变为“挖坑赋值”,降低时间复杂度return low;
}
void fast_sort( int array[] , int low , int high )
{if( low < high ){int index;index = Three_choose_one_optimize_fastSort(array,low,high);fast_sort(array,low,index-1);fast_sort(array,index+1,high);}
}

3.3 快速排序优化2—-优化递归操作:

递归对性能是有一定影响的,快排在其尾部有两次递归操作,如果待排序的序列划分极端不平衡,递归深度将趋近于n,而不是平衡时的logn。这就不仅仅是速度快慢的问题了,栈的大小是有限的,每次递归调用都会耗费一定的栈空间,函数的参数越多,每次递归耗费的空间也越多,因此,减少递归会大大提高性能

  • 下面是用一次迭代来换取一次递归的代码,此代码主要对快排的递归部分修改,中轴元素的选取和排序部分代码沿用优化1方案的。
/*************************
Author:tmw
date:2017-11-5
**************************/#include <stdio.h>
#include <stdlib.h>int Three_choose_one_optimize_fastSort( int array[] , int low , int high )
{int mid = ( low + high ) / 2;int temp;if( array[low] > array[high] ){temp = array[low];array[low] = array[high];array[high] = temp;}if( array[mid] > array[high] ){temp = array[high];array[high] = array[mid];array[mid] = temp;}//以上,high位置的元素为三者中的最大if( array[low] < array[mid] ){temp = array[low];array[low] = array[mid];array[mid] = temp;}//以上,low位置的元素为三者中第二大元素int target = array[low];while( low < high ){while( low < high && array[high] > target )high--;array[low] = array[high];while( low < high && array[low] < target )low++;array[high] = array[low];}array[low] = target;return low;
}void interate_replace_one_recursion_fastSort( int array[] , int low , int high )
{int index;while( low < high )//迭代换递归,这里从if换成while{index = Three_choose_one_optimize_fastSort(array,low,high);interate_replace_one_recursion_fastSort(array,low,index-1);low = index+1;}
}

3.4 快速排序优化3—-优化小数组时的排序方案

以上两种优化方法是充分利用了快速排序解决大数组排序强大的功能,那么相反的情况,当数组非常小,其实快速排序不如直接插入排序来的好。
本质原因还是因为快速排序用到了递归,在大量数据排序时,这点性能影响可以通过上面的优化方法忽略掉,但是对于一个只有几个元素的数组需要排序时,用快排就像“大炮打蚊子”。

解决方案就是设定一个判断分支:
当数组长度大于7,则使用优化2的快排
当数组长度小于7,则使用直接插入排序

(有资料认为7这个设定比较合理,也有人认为50合理,不论多少,有个这个思想就行啦~~~)

C语言快速排序算法及三种优化方式相关推荐

  1. php 快速排序函数,PHP实现快速排序算法的三种方法

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

  2. 快排的三种优化方式。

    对于快排而言,其核心在partition中,主要是对于pivot的选取上,所以我们可以按以下三种方案进行优化: 1.在数组长度大于某一个阈值范围时,我们进行递归快排,当数据长度小于阈值时,我们进行插入 ...

  3. 快速排序三种实现方式及其优化

    快速排序三种实现方式及其优化 1.关于快速排序 快速排序是分治法的一个应用. 根据分治法的思想,快速排序算法可描述为: 分解∶数组A[p-r]被划分为两个子数组A[p-q-1]和A[q+1,r],使得 ...

  4. c语言勾股定理程序流程图,方法总结1.表达算法的方法有自然语言.流程图和基本算法语句三种.先有自然语言.再画流程图.最后才能写出基本算法语句.即程序,——青夏教育精英家教网——...

    考点一:自然语言表示的算法 [内容解读]通过对解决具体问题过程与步骤的分析,体会算法的思想,了解算法的含义:对于某一问题往往可以设计出多种算法,通过选用步骤最少的.结构最好的算法. [命题规律]以选择 ...

  5. 三种快排及四种优化方式

    本文是转载文章,文章的来源:csdn博客 博主:silentsharer 文章: 三种快排及四种优化方式 博文地址:https://blog.csdn.net/hacker00011000/artic ...

  6. K-means聚类算法的三种改进(K-means++,ISODATA,Kernel K-means)介绍与对比

    原文:http://www.cnblogs.com/yixuan-xu/p/6272208.html K-means聚类算法的三种改进(K-means++,ISODATA,Kernel K-means ...

  7. 打散算法的三种解决方案及其选型场景

    简介:打散算法优缺点及选型场景 作者:闲鱼技术-华采 背景 打散是在推荐.广告.搜索系统的结果基础上,提升用户视觉体验的一种处理.主要方法是对结果进行一个呈现顺序上的重排序,令相似品类的对象分散开,避 ...

  8. 排序--Bubble的三种优化

    BubbleSort      冒泡排序是许多人接触的第一种排序方式,由于这种方式比较简单,所以大部分人也没有深入研究,所以写出的代码是这样的: void BubbleSort(int *arr, i ...

  9. C语言求最大公约数三种方法详解

    C语言求最大公约数三种方法详解 题目要求 常用写法(穷举法) 辗转相减法 辗转相除法 main函数 整体代码 题目要求 运行最大公约数的常用算法,并进行程序的调式与测试. 常用写法(穷举法) 从两个数 ...

最新文章

  1. Microsoft Sql Server Management studio与visual studio 建立连接数据库
  2. UVALive 4254 Processor(二分)
  3. 日服巫术online过驱动保护分析(纯工具)(工具+自写驱动)
  4. android studio gradle 打出jar,同时将依赖的第三方jar打包在一起
  5. Volley源码学习1--volley结构图
  6. 【故障分析】基于matlab轴承故障仿真信号时域波形图+幅度谱图【含Matlab源码 123期】
  7. html网站 放新闻 文件夹名字 是什么,服务器上传网页文件时应注意哪几点?
  8. 计算机英语词汇电子书,计算机英语词汇-打印版.pdf
  9. 玩转流量,天下无锅——IT运维人员的九阳神功(上)| 技术分享
  10. 用python结合matplotlib包,绘制带有误差棒和数值的柱状图,每根柱子配色不同
  11. NCS初探--基于nRF5340的blinky
  12. UML结构建模图———复合结构图
  13. matlab 12脉波变压器,12脉波整流电路MATLAB-Simulink仿真及谐波分析
  14. 分享 百度网盘搜索引擎原理以及实现部分源码
  15. 基于微信小程序+JavaWeb+SSM开发的图书借阅小程序
  16. 多个Ajax请求成功后再执行后续方法
  17. 什么是计算机图形学?(转自中国科学技术大学-刘利刚)
  18. cuda的tip: nvcc的-arch,-code选项
  19. P1443 马的遍历(洛谷)
  20. 以下为linux下64位c,64位ntohl()在C?

热门文章

  1. 微信小程序之联合百度API实现定位(6)
  2. 【工业控制系统】ICS (工业控制系统)安全简介第3 部分
  3. p-7-10装箱问题
  4. 安装mpich运行hpl测试
  5. 全网最全面、全详细的编码、解码知识!!!
  6. webp格式转换成jpg,webp转jpg超简单
  7. mov转gif怎么制作?怎么把mov视频转换成gif?
  8. Maximum Bipartite Matching
  9. 通用技术必修考试丨工具类认识与使用方法大全
  10. 中国发展及其人自动化_设计自动化时将面临的3个问题-及其解决方法