快速排序 【转】

简介: 来源:http://blog.csdn.net/cjf_iceking/article/details/7925470     还记得曾哥淡定的哼唱"七月份的前奏是狮子座~,八月份的尾巴也是狮子座~',狮子座的尾巴也是校园招聘的开始,祝愿毕业生们都能够找到满意的工作。

来源:http://blog.csdn.net/cjf_iceking/article/details/7925470

 

  还记得曾哥淡定的哼唱"七月份的前奏是狮子座~,八月份的尾巴也是狮子座~',狮子座的尾巴也是校园招聘的开始,祝愿毕业生们都能够找到满意的工作。如果你拿到太多的offer难以选择的时候,那就给每一份offer定上各项指标,算出权值,最后再用效率超高的快速排序来进行排序。

 

一. 算法描述

    快速排序:快速排序采用分治法进行排序,首先是分割,选取数组中的任意一个元素value(默认选用第一个),将数组划分为两段,前一段小于value,后一段大于value;然后再分别对前半段和后半段进行递归快速排序。其实现细节如下图所示:

二. 算法分析

平均时间复杂度:O(nlog2n)

空间复杂度:O(n) 

稳定性:不稳定

三. 算法实现

 1 /********************************************************
 2 *函数名称:Split
 3 *参数说明:pDataArray 无序数组;
 4 *           iBegin为pDataArray需要快速排序的起始位置
 5 *          iEnd为pDataArray需要快速排序的结束位置
 6 *函数返回:分割后的分割数位置
 7 *说明:    以iBegin处的数值value作为分割数,
 8            使其前半段小于value,后半段大于value
 9 *********************************************************/
10 int Split(int *pDataArray,int iBegin,int iEnd)
11 {
12     int pData = pDataArray[iBegin];    //将iBegin处的值作为划分值
13 
14     while (iBegin < iEnd)    //循环分割数组,使其前半段小于pData,后半段大于pData
15     {
16         while (iEnd > iBegin && pDataArray[iEnd] >= pData)    //从后向前寻找小于pData的数据位置
17             iEnd--;
18 
19         if (iEnd != iBegin)
20         {
21             pDataArray[iBegin] = pDataArray[iEnd];    //将小于pData数据存放到数组前方
22             iBegin++;
23 
24             while (iBegin < iEnd && pDataArray[iBegin] <= pData)
25                 iBegin++;
26             
27             if (iBegin != iEnd)
28             {
29                 pDataArray[iEnd] = pDataArray[iBegin];    //将大于pData数据存放到数组后方
30                 iEnd--;
31             }
32         }
33     }
34 
35     pDataArray[iEnd] = pData;    //此时iBegin=iEnd,此处存储分割数据pData
36     return iEnd;
37 }
38 
39 /********************************************************
40 *函数名称:QSort
41 *参数说明:pDataArray 无序数组;
42 *           iBegin为pDataArray需要快速排序的起始位置
43 *          iEnd为pDataArray需要快速排序的结束位置
44 *说明:    快速排序递归函数
45 *********************************************************/
46 void QSort(int* pDataArray, int iBegin, int iEnd)
47 {
48     if (iBegin < iEnd)
49     {
50         int pos = Split(pDataArray, iBegin, iEnd);    //获得分割后的位置
51         QSort(pDataArray, iBegin, pos - 1);           //对分割后的前半段递归快排
52         QSort(pDataArray, pos + 1, iEnd);             //对分割后的后半段递归快排
53     }
54 }
55 
56 /********************************************************
57 *函数名称:QuickSort
58 *参数说明:pDataArray 无序数组;
59 *           iDataNum为无序数据个数
60 *说明:    快速排序
61 *********************************************************/
62 void QuickSort(int* pDataArray, int iDataNum)
63 {
64     QSort(pDataArray, 0, iDataNum - 1);
65 }
View Code

四. 算法优化

    快排选用数组第一个元素作为分割元素,如果是一个已经基本有序的数组,那么时间复杂度将会提升到O(n2);可以从数组中随机选择一个元素作为划分数据,这样即使针对基本有序的数据来说,效率同样达到(nlog2n),优化后分割函数如下所示:
 1 int Split(int *pDataArray,int iBegin,int iEnd)
 2 {
 3     int rIndex = rand() % (iEnd - iBegin + 1);    //随机获得偏移位置
 4 
 5     int pData = pDataArray[iBegin + rIndex];    //将iBegin+rIndex处的值作为划分值
 6 
 7     while (iBegin < iEnd)    //循环分割数组,使其前半段小于pData,后半段大于pData
 8     {
 9         while (iEnd > iBegin && pDataArray[iEnd] >= pData)    //从后向前寻找小于pData的数据位置
10             iEnd--;
11 
12         if (iEnd != iBegin)
13         {
14             pDataArray[iBegin] = pDataArray[iEnd];    //将小于pData数据存放到数组前方
15             iBegin++;
16 
17             while (iBegin < iEnd && pDataArray[iBegin] <= pData)
18                 iBegin++;
19             
20             if (iBegin != iEnd)
21             {
22                 pDataArray[iEnd] = pDataArray[iBegin];    //将大于pData数据存放到数组后方
23                 iEnd--;
24             }
25         }
26     }
27 
28     pDataArray[iEnd] = pData;    //此时iBegin=iEnd,此处存储分割数据pData
29     return iEnd;
30 }
View Code
相关文章
vscode ctrl+/ 注释快捷键失效
首次安装vscode 不知道为何会快捷键失效,首先想到的就是键位冲突! 于是解决了。
5925 0
vscode ctrl+/ 注释快捷键失效
|
9月前
|
监控 Apache PHP
301重定向详细教程
301重定向是一种HTTP状态码,用于指示网页已永久移至新位置,对SEO和用户体验至关重要。本文详解其作用、设置方法(如通过控制面板、Apache的mod_rewrite模块、IIS的URL重写模块、PHP代码及HTML标签)及注意事项,帮助网站管理员顺利完成URL永久重定向,确保网站平稳过渡和长期发展。
1056 101
|
Linux 网络安全
linux服务器中如何卸载宝塔
linux服务器中如何卸载宝塔
5252 0
|
7月前
|
Ubuntu 安全 Linux
Linux错误排查:解决Ubuntu 20.4执行sudo apt-get update时出现的libnettle.so.6错误。
很有可能在你得到解决方案时,你也学到了不少Linux修复技巧。祝你处理计算机问题时顺利如麻!永远记得,各种问题总是像老鼠一样从意想不到的地方冒出来。但记住,不管它们跑到哪里,最终都逃不过你的捕鼠器。盖起你的计算机,拾起你的代码,大步向前!
199 28
|
8月前
|
缓存 NoSQL Redis
Redis原理—2.单机数据库的实现
本文概述了Redis数据库的核心结构和操作机制。
Redis原理—2.单机数据库的实现
|
10月前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是"将对象的创建与使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节。创建型模式分为5种:单例模式、工厂方法模式抽象工厂式、原型模式、建造者模式。
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
|
存储 NoSQL 关系型数据库
MongoDB中的索引操作总结
这篇文章总结了MongoDB中索引的概念、创建方法、常见操作指令、限制以及索引对查询效率的影响。
695 2
|
XML 存储 安全
探索 doc 和 docx 文件格式的区别
探索 doc 和 docx 文件格式的区别
650 3
|
存储 Windows
GitHub+PicGo+Typora搭建个人免费图床并实现md粘贴即上传
本文介绍基于Github平台与PicGo工具,构建免费、稳定的图床,并实现在Typora内撰写Markdown文档时,粘贴图片就可以将这一图片自动上传到搭建好的图床中的方法~
1266 3
GitHub+PicGo+Typora搭建个人免费图床并实现md粘贴即上传
|
供应链 监控 安全
深入探究ERP系统的仓库与库存管理模块
深入探究ERP系统的仓库与库存管理模块
867 7