快速排序:
快速排序算法的基本思路:
假设要对一个数组a进行排序,且a[0] = x。首先对数组中的元素进行调整,使x放在正确的位置上。同时,所有比x小的数都位于它的左边,所有比x大的数都位于它的右边。然后对于左、右两段区域,递归地调用快速排序算法来进行排序
简单举一个例子: 一个数组中有23, 46, 0, 8, 11, 18
如下图所示,我们假设最开始的基准元素是第一个值23,则首先用一个临时变量temp去存储基准数据,即temp=23;然后分别设两个指示标志low指向起始位置,high指向末尾。我们对数组扫描的方式是先从high开始
(1)首先从后半部分开始,如果扫描到的值大于基准数据就让 high-1,如果发现有元素比该基准值小,停止遍历。让 high 位置的值赋值给 low位置(如图18<temp),结果如下:
(2)然后开始从前往后扫描,如果扫描到的值小于基准数据就让low+1,如果发现有元素比该基准值大,停止遍历。让low位置的值赋值给high位置(如图46>=temp)
(3)然后在开始从后向前扫描,原理同(1),发现如图 11<=temp,则将 high 位置的值赋值给 low 位置,结果如下:
(4)然后再开始从前向后遍历,直到low=high循环结束,此时low或high的下标就是基准值正确的索引位置,如下图所示
从上面的一轮遍历我们很快了解到快速排序的本质就是把基准数大的都放在基准数的右边,把基准数小的都放在基准数的左边,这样就找到了该数据在数组中的正确位置。
以后采用递归的方式分别对钱半部分和后半部分排序,当前半部分和后半部分均有序时,该数组自然有序。
从上面的过程中可以看到:
① 先从队尾开始向前扫描且当low < high时,如果arr[high] > temp,则high–,但如果arr[high] < temp,则将high的值赋值给low,即arr[low] = arr[high],同时要转换数组扫描的方式,即需要从队首开始向队尾进行扫描了。
② 同理,当从队首开始向队尾进行扫描时,如果arr[low] < temp,则low++,但如果arr[low] > temp了,则需要将low位置的值赋值给high位置,即arr[high] = arr[low],同时将数组扫描方式换为由队尾向队首进行扫描.
③ 不断重复①和②,知道low>=high时(其实是low=high),low或high的位置就是该基准数据在数组中的正确索引位置.
代码实现如下:
package 蓝桥练习;
public class QuickSort {
public static void main(String[] args) {
int [] arr = {49,38,65,97,23,76,1,5,8,2,0,-1,22};
quickSort(arr,0,arr.length-1);
System.out.println("排序后:");
for(int i:arr) {
System.out.print(i+" ");
}
}
//快速排序的算法
public static void quickSort(int[] arr,int low,int high) {
if(low<high) {
//寻找基准值
int index = getIndex(arr,low,high);
//进行迭代对index之前和之后的数组进行相同的操作使整个数组变成有序
quickSort(arr,0,index-1);
quickSort(arr,index+1,high);
}
}
public static int getIndex(int[] arr,int low,int high) {
//基准数据
int temp = arr[low];
while(low<high) {
//当对尾元素大于等于基准数据时,向前挪动high指针
while( low < high && arr[high]>=temp) {
high--;
}
//如果对尾元素小于temp了,需将其值赋值给low
arr[low] = arr[high];
//当队首元素小于等于基准元素时,向后挪动low指针
while( low < high && arr[low]<=temp) {
low++;
}
//当队首元素大于temp了,需将其值赋值给high
arr[high] = arr[low];
}
//跳出循环时,low和high的值相等,此时low或high就是temp的正确索引
arr[low] = temp;
return low;
}
}