【基础算法】排序-复杂排序之二(快速排序)
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)
证明如下
快速排序是一种非常经典的排序,速度比归并排序有明显的提升。
那么有没有一种方法,它能够保证在分割的情况下,交换两个元素的时候,元素就能排到正确的位置上呢?因为这样就不需要额外的数组空间了。于是科学家发明了快速排序。
快速排序的基本思想是基于分割,与归并排序不同在于,它的分割方式不是等份分割,而是随机选取分割元素,然后通过交换的方式保证分割点前面的元素比它小,分割点后面的元素比它大。这下递归下去就能保证每个元素都交换到自己的位置上了。
前面我们提到了随机选取分割的元素,所以一般情况下我们会选择首个元素作为分割元素。
那么如何选择交换的元素呢?当然是双指针大法:定义两个指针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)
证明如下
快速排序是一种非常经典的排序,速度比归并排序有明显的提升。
相关文章推荐
- 【基础算法】排序-复杂排序之二(找出第K大的数)
- 【基础算法】排序-复杂排序之二(找出第K大的数)
- 【算法-排序之二】快速排序
- 【基础算法】排序-复杂排序之一(归并排序)
- 基础算法--排序:之快速排序
- 【基础算法】排序-复杂排序之三(堆排序)
- 基础算法之二 直接插入排序的三种实现
- 基础排序算法之快速排序(Quick Sort)
- 【基础算法】排序-简单排序之二(选择排序)
- 算法基础之排序—快速排序
- 【算法-排序之二】快速排序
- 【基础算法】排序-复杂排序之一(归并排序的两种优化讨论)
- 基础算法之排序--快速排序
- 基础排序算法之快速排序(Quick Sort)
- 算法基础之排序篇-快速排序
- PHP四种基础算法详解(冒泡排序、选择排序、插入排序、快速排序)
- 算法 - 排序 - 快速排序
- 一道看上去很吓人的算法面试题:如何对n个数进行排序,要求时间复杂度O(n),空间复杂度O(1)
- 一道看上去很吓人的算法面试题:如何对n个数进行排序,要求时间复杂度O(n),空间复杂度O(1)
- 算法总结系列之二: 快速排序(QuickSort)