快速排序(quicksort)是在实践中最快的已知排序算法,它的平均运行时间为O(N logN)。该算法之所以快,主要是由于非常精炼和高度优化的内部循环。——《数据结构与算法分析——C语言描述》。它的最坏时间复杂度O(N ²),但是可以避免。这个我们稍后再分析。
一、快排的原理
为了方便起见,本篇文章数列按从小到大排。
快排是分治思想的典型应用,快排的步骤大致如下:
1、选取枢纽元。
2、用两个指针分别指向数列的头尾。
3、头指针向前移动,遇到比枢纽元大的停下。尾指针向后移动,遇到比枢纽元小的停下。
4、当两个指针都停下时,交换两指针指向的元素。
5、两个指针交错时停止循环,即头指针在尾指针后面。
6、交换枢纽元与尾指针指向的元素。
7、对枢纽元左边的和右边的子序列重复进行1-6的操作。
为了方便讲述我们选枢纽元默认选取数列的第0号元素,但是这是不科学的。之后在枢纽元的选取方法会在文章末尾说明
初始状态
头指针向后移动尾指针向前移动
当两个指针都停下时,交换两指针指向的元素。
两个指针交错时停止循环,即头指针在尾指针后面。交换枢纽元与尾指针指向的元素。
二、C++源码实现
1 #include2 #define max 1000 3 using namespace std; 4 //快速排序的数组,定义快速排序的区间 5 void q_sort(int args[],int begin,int end){ 6 if (begin>=end)//bdgin<=end时结束程序 7 return ; 8 int k = begin;//枢纽元选取 9 int p = begin;//头位置指示 10 int q = end;//尾位置指示 11 while (p<=q) 12 { 13 if (args[p] > args[k] && args[q] < args[k]) { 14 int t = args[p]; 15 args[p] = args[q]; 16 args[q] = t; 17 } 18 if (args[p] <= args[k])//头指针移动 19 p++; 20 if (args[q] >= args[k])//尾指针移动 21 q--; 22 } 23 int t = args[q]; 24 args[q] = args[k]; 25 args[k] = t; 26 //左右子序列进行操作 27 q_sort(args, begin, q - 1); 28 q_sort(args, q + 1, end); 29 }
三、枢纽元选取
从快排的原理我们知道,如果想让时间复杂度尽可能的低,那我们的枢纽元一定是在排好序后的序列中位于中间部分的元素,这里写两种主要选取方法供参考,随机化选取法,三值取中值法。
随机选取法:
顾名思义,就是利用随机数产生器产生枢纽元。代码如下:
int piv_1(int begin, int end) { srand(int(time(NULL))); return rand() % end + begin; }
注意使用srand()、rand()要包含头文件
三值取中值法:
就是将数列中头元素,尾元素,中间元素选出来,然后比较三者的大小,选取在中间的元素
int piv_2(int begin, int end, int args[]) { int center = (end-begin) / 2; if (args[center] > args[end]) { swap(args[end], args[center]); } if (args[begin] > args[center]) { swap(args[begin], args[center]); } return center; }