快速排序基本思想
- 在数据集之中,选择一个元素作为”基准”(pivot)。
- 所有小于”基准”的元素,都移到”基准”的左边;所有大于”基准”的元素,都移到”基准”的右边。这个操作称为分区 (partition) 操作,分区操作结束后,基准元素所处的位置就是最终排序后它的位置。
- 对”基准”左边和右边的两个子集,不断重复第一步和第二步,直到所有子集只剩下一个元素为止。
public class Student {
//快速排序,是每次确定一个元素最终位置,再对其左、其右进行排序
public static void quickSort(int[] arr,int low,int high)
{
if(low>=high) //注意一开始要判断两个下标
return;
int element=arr[low]; //将元素保存起来
int i=low; //左指针
int j=high; //右指针
while(i<j)
{
//右
while(i<j&&arr[j]>=element) //注意是>=
j--;
if(i<j) //为了防止这种情况 比如12 13
{
arr[i]=arr[j];
i++;
}
//左
while(i<j&&arr[i]<element)
i++;
if(i<j)
{
arr[j]=arr[i];
j--;
}
}
arr[i]=element; //最终i==j跳出循环,所以用i、j都可以
quickSort(arr,low,i-1);
quickSort(arr,i+1,high);
}
public static void main(String[] args) {
int arr[] = new int[]{50, 1, 23, 32, 32, 322, 2, 89, 99, 67, 56};
int arrLen = arr.length;
quickSort(arr, 0, arrLen - 1);
for (int i = 0; i < arrLen; i++) {
System.out.print(arr[i] + " ");
}
}
}
当初始的序列整体或局部有序时,快速排序的性能将会下降,此时,快速排序将退化成冒泡排序
一、时间复杂度
最坏时间复杂度O(n^2):每次划分的结果都是基准关键字的左边(或右边)序列为空,而另一边区间中的记录仅比排序前少了一项
最好时间复杂度O(nlogn):每次划分结果都是基准关键字左右两边的序列相等或相差1
平均复杂度O(nlogn)
二、空间复杂度
快速排序过程中需要一个栈空间来实现递归
O(logn)
三、基准关键字的选取
基准关键字的选取是决定快速排序算法性能的关键
①三者取中(low、mid、high)
②取随机数( low high 随机数)
四、不稳定排序
在中枢元素和序列中一个元素交换的时候,很有可能把前面的元素的稳定性打乱。
还是看一个小实例:6 4 4 5 4 7 8 9,第一趟排序,中枢元素6和第三个4交换就会把元素4的原序列破坏,所以快速排序不稳定。