您的位置:首页 > 其它

【基础算法】排序-复杂排序之二(快速排序)

2014-10-30 00:05 225 查看
归并排序在时间复杂度上大大的优化了,但是出现了一个问题,就是额外线性空间的使用。因为在归并排序的过程中,sub1数组和sub2数组只能保证一个元素排到正确的位置,另一个不能保证,所以必须用额外的空间来保存这个元素。

那么有没有一种方法,它能够保证在分割的情况下,交换两个元素的时候,元素就能排到正确的位置上呢?因为这样就不需要额外的数组空间了。于是科学家发明了快速排序。

快速排序的基本思想是基于分割,与归并排序不同在于,它的分割方式不是等份分割,而是随机选取分割元素,然后通过交换的方式保证分割点前面的元素比它小,分割点后面的元素比它大。这下递归下去就能保证每个元素都交换到自己的位置上了。

前面我们提到了随机选取分割的元素,所以一般情况下我们会选择首个元素作为分割元素。

那么如何选择交换的元素呢?当然是双指针大法:定义两个指针i,j。i指向除掉分割元素的第一个元素,j指向最后一个元素。如果A[i]<partition, 说明i这个位置满足分割的要求,i++就可以了,同理,如果A[j]>partition, 那么说明j也满足位置分割的要求,j--就可以了。

所以选择交换的两个元素即A[i]不满足A[i]<partition和A[j]不满足A[j]>partition。这个时候交换i个j即可。

什么时候结束分割呢?

当i>=j的时候就可以结束了,这个时候j的位置正好比partition小,而i的位置正好比partition大,交换partition和j就可以了。

while (true) {

while (more(array[left], array[++i]))
if (i == right)
break;
while (more(array[--j], array[left]))
if (j == left)
break;

if (i >= j)
break;
exchange(array, i, j);
}


记住这里一定是i>=j就要跳出,因为当i==j的时候,i和j指向的那个元素一定小于partition且是最后一个元素。如果不跳出的话,数组会出现越界
当i>j的时候,i指向的元素一定比partition大,j指向的元素一定比partition小。

边界条件非常重要。

接下来是分割部分,其实挺简单,就是分成partition, left and right三部分就可以了

public static void quickSort(int[] array, int left, int right) {
if (left >= right)
return;
int partitionIndex = partition(array, left, right);
quickSort(array, left, partitionIndex - 1);
quickSort(array, partitionIndex + 1, right);
}


快速排序的时间复杂度为O(NlogN)
证明如下



快速排序是一种非常经典的排序,速度比归并排序有明显的提升。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  快速排序 算法 优化