基本思想
用首元素 x 作划分标准,将输入数组 A划分成不超过 x 的元素构成的数组 AL,大于 x 的元素构成的数组 AR. 其中 AL, AR从左到右存放在数组 A 的位置。递归地对子问题 AL和 AR 进行排序,直到子问题规模为 1 时停止.
划分过程:用首元素作为基准,从后往前找第一个比首元素小的元素,找到后停止,然后从前向后找第一个比首元素大的元素,然后将大元素与小元素做交换,最后返回划分的位置。
时间复杂度分析
最坏情况下时间复杂度:
W(n) = W(n-1) + n-1,W(1) = 0,
则W(n) = n(n-1)/2最好划分情况下时间复杂度:
T(n) = 2T(n/2) + n-1,T(1) = 0
则T(n) = nlogn平均情况时间复杂度: nlogn
所以最坏情况下时间复杂度:O(n^2),平均情况时间复杂度:nlogn,所以要注意首元素的选取即基准元素的选取
java代码
package com.cn;
import java.util.Arrays;
public class QuickSort
{
public static void main(String[] args)
{
QuickSort qc = new QuickSort();
int[] arr = { 45, 36, 18, 53, 72, 30, 48, 93, 15, 36 };
qc.sort(arr);
System.out.println(Arrays.toString(arr));
}
public void sort(int[] arr)
{
sort(arr, 0, arr.length - 1);
}
public void sort(int[] arr, int start, int end)
{
if (start < end)
{
int location = sortFirstItem(arr, start, end);
sort(arr, start, location - 1);
sort(arr, location + 1, end);
}
}
/**
* 排序第一个元素
*
* @param arr
* @param start
* @param end
* @return 第一个元素排序后的位置
*/
//以第一个元素为基准,左面的元素小于基准,右面的元素大于基准(划分过程)
public int sortFirstItem(int[] arr, int start, int end)
{
int firstItem = arr[start];
int first = start + 1, last = end;
while (first < last)
{
//优先找小的元素
while (firstItem < arr[last] && first < last)
last--;
//找大的元素
while (firstItem >= arr[first] && first < last)
first++;
//小元素与大元素做交换
if (first < last)
{
int tmp = arr[first];
arr[first] = arr[last];
arr[last] = tmp;
}
}
// 与最后一个最小元素交换
if (arr[last] < firstItem)
{
arr[start] = arr[last];
arr[last] = firstItem;
return last;
}
// 元素就排在当前位置
return start;
}
}
注意:
在划分过程中一定要注意边界问题的处理
如在划分过程中返回值的处理:
- 如果先从先往后找第一个比首元素大的元素,再从后往前找第一个比首元素小的元素,则在内部循环结束时,找到的元素是比首元素大的元素,此时如果该元素与首元素交换就会出现问题。
- 如果首元素比所有元素都小,first = start+1,last = end,则在从后往前找的过程中就会找到start+1的位置停止,因为此时fist = last,此时序列的划分位置就应该是首元素的位置,所以应该返回start
- 还有一种情况就是:如果首元素比所有元素都小,first = start,last = end,在从后往前找时会找到first的位置停止,此时fist = last = start,则返回last就可以了。
代码如下:
public int Divide(int[] a,int start,int end){
int i,j,k,standard;
standard = a[start];
i = start;
j = end;
while(i<j){
while(standard<=a[j]&&i<j)j--;
while(standard >= a[i]&&i<j)i++;
if(i<j)
{
k=a[i];
a[i] = a[j];
a[j] = k;
}
}
if(standard < a[i]){
a[start] = a[i];
a[i] = standard;
}
return i;
}