快速排序可能是应用最广泛的排序算法。快速排序流行的原因是它实现简单、适用于各种不同的输入数据且在一般应用中比其他排序算法都要快很多。此次,我们来学习一下快速排序算法。
一、快速排序算法含义
快速排序是一种分治的排序算法。它会在数组中选择一个基准元素,讲数组分为两部分,使得第一部分中的所有元素都小于或等于基准元素,而第二部分中的所有元素都大于基准元素。对第一部分和第二部分递归的应用快速排序算法。
二、快速排序算法过程
例如:
对数组 [5 2 9 3 8 4 0 1 6 7 ]
进行快速排序
基准元素的选择会影响算法的性能。在理想情况下,应该选择能平均划分两部分的基准元素。为了简单起见,假定将数组的第一个元素选为基准元素。
如下图:
根据基准元素,将数组分为左边和右边的数组,并选择第一个为基准元素。
对左边< 5的数组进行快速排序
基准元素4又将数组划分为一个数组(0 2 1 3),然后对其进行快速排序
基准元素2又将数组仅分为(2 1 3),然后对其快速排序
然后,左边 <5 的数组已经快速排序完成。对右边 >5的数组递归的运用快速排序。
如上图流程可更能了解快速排序的原理过程。但是要实现这个过程就要有实际的切分方法。
三、快速排序算法的过程方法实现
要实现快速排序的过程,关键在于切分。
切分过程使得数组满足下面三个条件。
- 对于某个pivotIndex,a[pivotIndex]已经排定;
- a[first]到a[pivotIndex-1]中的所有元素都不大于a[pivotIndex];
- a[pivotIndex+1]到a[last]所有元素都不小于a[pivotIndex];
要完成这个切分,就要实现切分的方法。一般是去a[first]为切分元素(pivot)。然后我们从数组左端开始向右扫描直到找到一个大于等于它的元素,在从右边扫描直到找到一个小于等于它的元素。然后交它们的位置。如此继续。我们就可以保证左边的不小于切分元素,右边的不大于切分元素。
当两个指针相遇时,我们只需要将切分元素a[first]和左子数组最右侧元素a[high]交换返回[high]即可。
切分过程所示:
对于随机数组一次递归的动态过程如下
四、快速排序算法的实现
public class QuickSort {
public static void quickSort(int[] list, int first, int last) {
if (last > first){
int pivotIndex = partiton(list,first,last);
quickSort(list,first,pivotIndex-1);
quickSort(list,pivotIndex+1,last);
}
}
public static int partiton(int[] list, int first, int last) {
int pivot = list[first];
int low = first +1;
int high = last;
while (high > low){
while (low <= high && list[low] <= pivot) low++;
while (low <= high && list[high] > pivot) high--;
if (high > low && list[high] > list[low]){
int temp = list[high];
list[high] = list[low];
list[low] = temp;
}
}
while (high > first && list[high] >= pivot) high--;
if(pivot > list[high]){
list[first] = list[high];
list[high] = pivot;
return high;
}
else {
return first;
}
}
///另一种方式写快速排序
public static int[] qsortA(int arr[],int first,int last) {
int pivot = arr[first];
int low = first +1;
int high = last;
while (high > low) {
while ((low <= high)&&(arr[low] <= pivot)) {
low++;
}
while ((low <= high)&&(arr[high]>= pivot)) {
high--;
}
if (high > low){
int temp = arr[low];
arr[low] = arr[high];
arr[high] = temp;
}
}
while (high > first && arr[high] >= pivot){
high--;
}
if (pivot >arr[high]){ //此时基准元素大于下标元素,将其对换,满足左边的都小于基准元素,右边的都大于基准元素(数组的拆分)
arr[first] = arr[high];
arr[high] = pivot;
}
if (low -1 > first){
arr = qsortA(arr,first,low-1);
}
if (high +1 < last){
arr =qsortA(arr,high+1,last);
}
return (arr);
}
public static void main(String[] args) {
int[] a ={5,2,6,9,6,1,2,0,3,6,8,11,68,75};
qsortA(a,0,a.length-1);
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]+ " ");
}
}
}
运行结果:
0 1 2 2 3 5 6 6 6 8 9 11 68 75