排序算法之快速排序

2014-11-24 02:08:35 · 作者: · 浏览: 1
快排:
(1)选择一个枢轴元(pivot), 将数组划分左右两个子数组,左边的数组元素小于pivot,
右边数组元素大于pivot。
(2)用上述做法独自处理两个子数组,直到所有子数组元素个数为1时停止。
优化:主要有三种优化措施
(1)数组的划分策略
(2)枢轴元的选取
(3)子数组元素个数小于一定量时,采用其它排序方法。
一、数组的划分策略:
(1)单向划分
l 、u为数组的边界,用于界定数组。
(l, lastlow] 之间的元素小于pivot
(lastlow, i) 之间的元素大于等于pivot
[i, u] 之间的元素标示尚未进行处理的元素
+ View Code
 这种划分有一个弊端,就是当数组中所有元素都相同的时候,退化成O(N * N) 排序算法,变成如下划分: 
下一次排序区间为(lastlow, i],这类似于插入排序啦。
(2)双向划分
针对于单向划分的缺点,采用双向划分。
(l, i) 为小于等于pivot的元素
(j, pivot)为大于等于pivot的元素
+ View Code
当数组中所有元素都是一样的时候,双向划分可以将数组均匀的划分成两个子数组,但是,
却增加了交换次数,相当于每一次划分,都要将[l, u] 中的元素reverse。
(3)“ 宽支点“ 划分
将等于枢轴元的元素全部搬到一起,这样,当数组元素全相同的时候,减少递归次数。
将与枢轴元相同的元素集中到一起,加速快排。划分如下:
思路:
先将相等元素拷贝到数组两端,待划分结束后,将其拷贝到相应位置。
[l, a) 等于枢轴元的元素
(d,u] 等于枢轴元的元素
[a, b) 小于枢轴元的元素
(c, d] 大于枢轴元的元素
+ View Code
  
二、选枢轴元:
较好的选择枢轴元,可以将元数组划分成两个数量接近的子数组。
(1) 始终选择数组的第一个元素作为枢轴
(2)随机选取一个元素
(3)三中值
上述例子中都采取了第一个元素作为枢轴元,这并不是一种好的方法,可能导致劣质分割。
可以采用随机方法,即 swap(l, rand() % ( u - l + 1) + l);
三中值做法实例:
选取数组第一个,中间,最后一个元素,将其从小到大进行排序,选取中间值作为枢轴元。
三、小数组
当子数组小于一定量时,采用插入排序能得到更好的体验。
结合三中值与小数组,实现快速排序如下:
+ View Code
median中,由于三个元素已经排序,所以, arr[m] < arr[u], 所以,将枢轴元至于
u - 1的位置,因为arr[u]大于枢轴元,想当于已经排好序啦。
而在qsort中,i = l + 1, 也同上述解释,即arr[l] 小于arr[pivot],不需要在进行比较啦