快速排序
核心思想:
- 选区基准元素,将序列分为两部分,前半部分小于基准元素,后半部分大于基准元素。我们要做的就是左右扫描,当左边扫描到大于基准元素和右边扫描到小于基准元素 时,交换左右元素的位置,继续扫描交换,直到最后左右指针重合时,将基准元素插入中间位置,也就是将基准元素与重合指针指向的元素交换。然后将左右两部分分别进行快速排序。
具体操作:
- 选取一个基准元素(可随便选,为了编码方便,一般选取第一个元素或者最后一个元素),这里选取最后一个元素
- 左指针从左向右扫描直到大于基准元素或者左指针已经到达最右边(指向的基准元素),
- 右指针从右向左扫描直到小于基准元素或者与左指针重合。
- 判断左右指针是否相等:
不相等:将左右指针元素进行交换,继续扫描直到左右指针相等为止。
相等:将基准元素与指针位置元素交换,结束一次快速排序。再分别对基准元素左右的元素分别进行快速排序
时间复杂度:
- O(nlog2^n)
- (因为快速排序,每次递归都将一个序列分为两份,1——>2——>4——>8.类似一个树结构,所以时间复杂度为O(nlog2^n))
适用场景:
- 快速排序是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短;
稳定性:
扩充理解:
- 根据基准元素的选择,扫描顺序也会有所变化,为了方便编码,一般选取第一个元素或者最后一个元素。
- 扫描时左右等于基准元素时,指针都要移动。(否则等于时就交换,会出现滞留的情况)
- 当左右元素交互的时候,左右指针不用移动,因为同时移动可能会导致i>j。
- 基准元素加入左右边界中(因为基准元素可能已经是最大值最小值,i,j重合时交互就不会出错)
java源码:
public class 快速排序 {
public static void main(String[] args) {
int a[] = {5,2,4,1,33,44,66,33,5,356};
quickSort(a);
for(int t:a) System.out.println(t);
}
public static void quickSort(int a[]){
int flag = a.length - 1;
int left = 0;
int right = a.length - 1;
onceQuickSort(a,flag,left,right);
}
public static void onceQuickSort(int []a,int flag,int left,int right){
int i = left;
int j = right;
if(left >= right)return;
while (i != j){
while (a[i] <= a[flag] && i != right){
i++;
}
while (a[j] >= a[flag] && j != i){
j--;
}
if(i != j){
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
int temp = a[i];
a[i] = a[flag];
a[flag] = temp;
onceQuickSort(a,i-1,left,i-1);
onceQuickSort(a,right,i+1,right);
}
}