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

 

一. 算法描述

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

快速排序 【转】_无序数组

二. 算法分析

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

空间复杂度:O(n) 

稳定性:不稳定

三. 算法实现


快速排序 【转】_数据_02快速排序 【转】_数据_03


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),优化后分割函数如下所示:

快速排序 【转】_数据_02快速排序 【转】_数据_03


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