思想:每次循环确定一个元素的最终位置,每次循环设置当前数组的第一个元素为基准值,这一趟循环中,每个元素和这个基准值进行比较。
时间复杂度:最好(n*log(n)),最坏(n*2),平均(n*log(n))
Python版本:
# 快速排序
class Solution:
def QuickSort(self, Arr):
n = len(Arr)
self.Sort_(Arr, 0, n - 1)
return Arr
def Sort_(self, arr, left, right):
if left>=right:return #终止条件
i = left
j = right
pivot = arr[left] # 注意这里是left,不能写0
while i < j:
while i < j and arr[j] >= pivot:
j -= 1
if i < j:
arr[i] = arr[j]
while i < j and arr[i] <= pivot:
i += 1
if i < j:
arr[j] = arr[i]
arr[i] = pivot
self.Sort_(arr, left, i - 1)
self.Sort_(arr, i + 1, right)
print(Solution().QuickSort([3, 5, 1, 2, 5, 7, 9, 0]))
Java版本:
public class QuickSort {
public static void main(String[] args) {
int[] arr = new int[]{3, 5, 1, 2, 5, 7, 9, 0};
FastSort(arr,0,arr.length-1);
System.out.println(java.util.Arrays.toString(arr));
}
public static void FastSort(int[] arr,int left,int right){
if (left>=right){ //终止条件始终,首先写
return;
}
int pivot = arr[left];
int i = left;
int j = right;
while(i<j){
while(i<j && arr[j]>=pivot){//边界判断
j--;
}
if(i<j){
arr[i] = arr[j];//值的交换
}
while (i<j && arr[i]<=pivot){//边界判断
i++;
}
if (i<j){
arr[j] = arr[i];//值的交换
}
arr[i] = pivot;
}
FastSort(arr,left,i-1);
FastSort(arr,i+1,right);
}
}
问题及优化:
当每次都能平均划分序列时,此时时间复杂度为最优;而当每次划分都是划分成一个元素和其他序列时,此时快速排序退化为冒泡排序;
优化:每次设置基准数时,采用“三者取中”的原则:在没趟划分前比较分段中第一个、最后一个和位置居中的三个记录的关键码,取这3个关键码对应的值中数值处于中间大小的值,将这个居中值的记录与首记录交换。(注意,可以减少最坏情况出现的概率,但是无法消除最坏情况)