快速排序(QuickSort)是对冒泡排序算法的一种改进。
快速排序通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
快速排序算法通过多次比较和交换来实现排序。
(1)首先设定一个分界值,通过该分界值将数组分成左右两部分。
(2)将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。
此时,左边部分中各元素都小于或等于分界值,而右边部分中各元素都大于或等于分界值。
(3)然后,左边和右边的数据可以独立排序。
对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。
右侧的数组数据也可以做类似处理。
(4)重复上述过程,可以看出,这是一个递归定义。
通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。
当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。
(图片参考:https://blog.csdn.net/pengzonglu7292/article/details/84938910)
此处排序数据:{5,3,7,6,4,1,2,9,10,8}
/** * 快速排序 * @Author distance */ public class QuickSort { public static void quickSort(int[] num, int left, int right) { if (left > right) { return; } int i = left, j = right; int key = num[left], temp; // 开始 left 位置作为基准值 while (i != j) { while (j > i && num[j] >= key) { // 从右往左找第一个小于 key 值的元素 j --; } while (i < j && num[i] <= key) { // 从左往右找第一个大于 key 值的元素 i ++; } if (i < j) { temp = num[i]; num[i] = num[j]; num[j] = temp; } } temp = num[left]; // 交换 left 位置和 i 位置的值,同时 i 位置作为基准值 num[left] = num[i]; num[i] = temp; quickSort(num, left, i - 1); // 递归对 i 左边快排 quickSort(num, i+1, right); // 递归对 i 右边快排 } public static void sort(int[] num) { quickSort(num, 0, num.length - 1); } public static void main(String[] args) { int[] num = {5,3,7,6,4,1,2,9,10,8}; QuickSort.sort(num); for (int i = 0; i < num.length; i++) { System.out.print(num[i] + " "); } } }
快速排序的一次划分算法从两头交替搜索,直到low和hight重合,因此其时间复杂度是 O ( n ) O(n) O(n) ;而整个快速排序算法的时间复杂度与划分的趟数有关。
理想的情况是,每次划分所选择的中间数恰好将当前序列几乎等分,经过 log 2 n \log_2 n log2n 趟划分,便可得到长度为1的子表。这样,整个算法的时间复杂度为 O ( n log 2 n ) O(n\log_2 n) O(nlog2n) 。
最坏的情况是,每次所选的中间数是当前序列中的最大或最小元素,这使得每次划分所得的子表中一个为空表,另一子表的长度为原表的长度-1。这样,长度为n的数据表的快速排序需要经过n趟划分,使得整个排序算法的时间复杂度为 O ( n 2 ) O(n^2) O(n2)。
为改善最坏情况下的时间性能,可采用其他方法选取中间数。通常采用“三者值取中”方法,即比较 num[left]、num[right] 和num[(left + right)/2],取三者中关键字为中值的元素为中间数。
可以证明,快速排序的平均时间复杂度也是 O ( n log 2 n ) O(n\log_2 n) O(nlog2n)。因此,该排序方法被认为是目前最好的一种内部排序方法。
所以快速排序的平均时间复杂度为 O(n*logn)。
快速排序中,开始通常用数组的第一个数作为关键数据(基准数),然后将所有比它小的数都放到它左边,所有比它大的数都放到它右边,这个过程称为一趟快速排序。
值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。
所以快速排序是一种不稳定排序算法。