1. 快速排序原理理解:
首先考虑,如何在不排序全部数组的情况下,只将第一个元素的最终序列位置找到呢?方法就是,将比这个元素大的数放到右半区,将比这个元素小的数放到左半区,那么这个元素插进这两半区的中间就行了呀。而快速排序就是将第一个元素排好之后,再将左右半区各看成是一个数组,再次排出两个半区第一个元素的最终序列,那么一直递归下去,直到每一个元素都排序好。
(以下是具体操作流程:
1.第一个元素作为基准值。
2.在最左边和最右边各设置一个虚拟指针,左指针一格格向右移动,右指针一格格向左移动。
3.每当左指针指向比基准值大的数就停下,每当右指针指向比基准值小的数就停下。
4.两个指针停下后,交换两个指针指的数。这时,大的数就会跑到右边,小的数就会跑到左边
5.一直这样移动、停下、交换、移动、停下、交换、移动、…,直到两个指针撞在一起。
6.这时所有大的数都会跑到右半区,所有小的数都会跑到左半区。我们就把基准值放进左右半区中间,此时基准值索引就是排序准确的了。
7.重复以上操作,不断细分左右半区直到排序完成。)
2. 快速排序java实现:
/**快速排序(从小到大)
* @param arr
* @param left 待排序最左边索引
* @param right 待排序最右边索引
*/
public static void QuickSort(int[] arr,int left,int right) {
//如果数组只有一个数,结束
if(left >= right)return;
//设置最左边的元素为基准值
int key = arr[left];
int i = left;//i为左边指针
int j = right;//j为右边指针
while(i < j) {
//j向左移,直到指向比key小的索引。
//j先向左移,先指出一个小的索引,不然j、i相撞时出错。
while(arr[j] >= key && i < j) {
j--;
}
//i向右移,直到指向比key大的索引
while(arr[i] <= key && i < j) {
i++;
}
//i和j指向的元素交换
if(i < j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
//当 i 和 j 相等时,将基准值索引和两个指针指向的索引交换
arr[left] = arr[i];
arr[i] =key;
//递归
QuickSort(arr,left,i - 1);
QuickSort(arr,i + 1,right);
}
3. 快速排序平均时间复杂度理解:O(n*logn)
第一轮运行1次QuickSort,
第二轮运行2次,
第三轮运行4次,
第n轮运行2^(n-1)次QuickSort。
假设一共有2 ^ n个元素,那么第n轮即可完成排序。
因此假设一共有n个元素,那么第logn轮即可完成排序。
又因为无论是哪一轮,无论那一轮分出了多少组,无论那一轮运行了多少次QuickSort,都需要比较n个元素。
所以平均时间复杂度为O(n*logn)。
4. 快速排序最坏情况以及最坏时间复杂度:O(n^2)
最坏情况为,每一轮分不成两组,每一轮都只能把基准值索引放到第一个或者最后一个,因此一共需要n轮。
因此,最坏时间复杂度为O(n^2)。
正序排列的越有序越坏,逆序排列的越有序越坏
举个例子,比如要从小到大排列,1 2 3 4 5 6 7 8 9 10
就排{1,2,3,4,5,6,7,8,9,10},
或者{10,9,8,7,6,5,4,3,2,1},都是最坏情况
因为这几种情况每一轮只能排出一个最大的或者最小的。