这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战
一、代码
public void quickSort(int[] arr) {
sort(arr,0,arr.length - 1);
}
private void sort(int[] arr,int begin,int end) {
if (begin >= end) return;
int mid = partition(arr,begin,end);
sort(arr,begin,mid - 1);
sort(arr,mid + 1,end);
}
private int partition(int[] arr,int begin,int end) {
int left = begin;
int right = end;
int p = (int)(Math.random() * (end - begin + 1)) + begin;
int v = arr[p];
arr[p] = arr[begin];
while (left < right) {
while (left < right) {
if (arr[right] >= v) {
right--;
} else {
arr[left++] = arr[right];
break;
}
}
while (left < right) {
if (arr[left] <= v) {
left++;
} else {
arr[right--] = arr[left];
break;
}
}
}
arr[left] = v;
return left;
}
二、描述
- 快速排序在一般情况下,效率会比其他的排序算法要高许多。快速排序是将一个数组拆分成两个子数组,并在子数组中进行排序,而后继续对子数组进行递归拆分。所以说快速排序也是一种利用分治思想的排序算法。
private void sort(int[] arr,int begin,int end) {
if (begin >= end) return;
int mid = partition(arr,begin,end);
sort(arr,begin,mid - 1);
sort(arr,mid + 1,end);
}
- 首先判断数组排序开始的下标是否越过数组排序终止的下标。如果这两个下标相等的话,说明这是拆分之后只有一个元素的子数组,所以我们就不需要对这个子数组进行排序了。
- 然后调用切分函数,以获取当前数组的切分点(就是这个数组的切分下标),经过排序后切分点左边的数总是小于切分点右边的数,最后对子数组进行递归就行了。
private int partition(int[] arr,int begin,int end) {
int left = begin;
int right = end;
int p = (int)(Math.random() * (end - begin + 1)) + begin;
int v = arr[p];
arr[p] = arr[begin];
while (left < right) {
while (left < right) {
if (arr[right] >= v) {
right--;
} else {
arr[left++] = arr[right];
break;
}
}
while (left < right) {
if (arr[left] < v) {
left++;
} else {
arr[right--] = arr[left];
break;
}
}
}
arr[left] = v;
return left;
- 先对数组中进行随机取数(如果在一组已经排序的数组中切分元素取最后一个或者第一个,就会大大降低性能了),因为我们从右边开始的,所以把它和左边第一个元素换一下位置。
- while 循环里面的 第一个 while 循环里,遇到大于或者等于切分元素的元素,右指针就继续向左边移动;若是遇到小于切分元素的元素,就把它放到左指针指向的位置(因为此前左指针指向的数组位置已经属于空闲的了,同时此位置也就会是空闲的,因为它的元素已经移向了其他位置了)。
- while 循环里面的 第二个 while 循环里,遇到小于或者等于切分元素的元素,左指针就继续向右边移动;若是遇到大于切分元素的的元素,就把它放到右指针指向的位置,该指针指向位置也将会空闲。 注意点:
- 原地切分。我们不需要借助其他的辅助数组,而是在原来的数组上进行操作。
- 越界问题。在写代码时要十分注意。
- 数组内的元素要保持随机性。
写在最后:算是第一篇博客了,文中的描述可能会有错,欢迎指出,哈哈哈哈!碎觉了
`