快速排序
思想构思
分治法:比大小,再分区
1.从序列中选择一个基点元素(pivot)
默认选择索引为0的元素为基点元素
2.分区:将比基点大的数放在他的右边,比它小的放在他的左边
等于基点元素的放哪边都可以
3.对子序列1,2进行操作,直到不能再分割(子序列中只剩下一个元素)
快速排序的本质:是将每一个元素都转换成基点元素
例题:
从小到大排序
7 | 5 | 2 | 8 | 9 |
---|---|---|---|---|
left | right |
步骤
-
先确定一个基点元素,一般以索引为0的数为基点元素(基点元素:7)
比7小的数放在7的左边,把比7大的数放在7的右边
-
先定义两个索引left和right,要找出基点元素真正的索引位置,当left和right相等时就是基点元素真正的索引位置(left是索引为0的位置,right是数组索引最后的一个位置)
-
排序是从后面往前找,一旦找到比基数点小的数就和基点元素换位置就要和基点元素交换了位置,就要从前面向后找比基数大的数,一旦找到比基数点大的数就和基点元素换位置就要和基点元素交换了位置,交换了位置就要换方向比大小
-
7比9小位置不变,right--向前到7的位置
-
7和7比位置可以不变(也可以换位置),right--到3的位置
-
7和3比大互换位置
-
换方向进行比较,8和7比大换位置
-
换方向进行比较,10和7比大于7位置不变
-
6和7比小于7互换位置
-
换方向进行比较,2和7比小于7位置不变,left++
-
left和right在6的位置上重合,那么6位置的索引就是基点元素最终的索引
-
数组(基点元素:7)
第一次排序
7 | 8 | 2 | 6 | 10 | 3 | 7 | 9 |
---|---|---|---|---|---|---|---|
3 | 6 | 2 | 7 | 10 | 8 | 7 | 9 |
4.在基点元素左边的数都比基点元素小,在基点元素右边的数都比基点元素大
5.分成了两个子序列,用同样的方法对子序列进行排序(左边的子序列基点元素为3,右边的子序列基点元素为10)
第二次排序
3 | 6 | 2 | 7 | 10 | 8 | 7 | 9 |
---|---|---|---|---|---|---|---|
2 | 3 | 6 | 7 | 9 | 8 | 7 | 10 |
6.在分子序列用同样的方法对子序列进行排序
第三次排序
2 | 3 | 6 | 7 | 9 | 8 | 7 | 10 |
---|---|---|---|---|---|---|---|
2 | 3 | 6 | 7 | 7 | 8 | 9 | 10 |
代码实现
import java.util.Arrays;
public class Demo2 {
public static void main(String[] args) {
int[] arr={56, 38, 65, 97, 23, 22, 76, 23, 5, 8, 2, 78, 43, 22};
sort(arr,0,arr.length-1);
System.out.println("排序后:"+ Arrays.toString(arr));
}
private static void sort(int[] arr, int left, int right) {
if(left<right){
//基点的真实索引
int index=getIndext(arr,left,right);
//递归
//左子序列
sort(arr,left,index-1);
//右子序列
sort(arr,index+1,right);
}
}
private static int getIndext(int[] arr, int left, int right) {
//基点元素
int i=arr[left];
while (left<right){
// 当队尾的元素大于等于基点元素时,向前挪动right指针
while (left<right && arr[right]>=i){
right--;
}
//如果队尾元素小于基点元素了,需要将其赋值给索引为left的位置
arr[left]=arr[right];
// 当队首元素小于等于基点元素时,向前挪动left指针
while (left<right && arr[left]<=i){
left++;
}
//如果队尾元素大于基点元素了,需要将其赋值给索引为right的位置
arr[right]=arr[left];
}
// 跳出循环时left和right相等,此时的left或right就是i的正确索引位置
arr[left]=i;
// 返回i的正确位置
return left;
}
}