简介:快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法。
其基本思想为:任取待排序元素序列中 的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右 子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。
因为快速排序采用了分治算法的思想,所以排序速率相对较快。
正文
下面叙述一下快速排序的思想:
第一步:选择一个基准值。(选择方法很多,目前选择数列里最后一个作为基准值的方法。)
第二步:遍历整个区间,把所有的数和基准值作比较,并进行数据移动,使得
①比基准值小的数,放到基准值的左边
②比基准值大的数,放到基准值的右边
第三步:采用分治算法,将整个区间分为三个部分:[left, div - 1], [div], [div + 1, right].
此处采用递归的方法来实现分治算法,递归的终止条件就是:
①小区间的size == 0
②小区间的数已经有序,也就是只有一个元素的时候。
接下来就是重头戏了,将数组分为三部分有三种方法:
1、hover法:
流程:
具体进行过程如下:
代码如下:
int Partition_1(int arr[], int left, int right){//hover法
int begin = left;
int end = right;
while (begin < end){
while (begin < end && arr[begin] <= arr[right]){
begin++;
}
while (begin < end && arr[end] >= arr[right]){
end--;
}
Swap(arr + begin, arr + end);
}
Swap(arr + begin, arr + right);
return begin;
}
2、挖坑法:
流程:
代码如下:
int Partition_2(int arr[], int left, int right){ //挖坑法
int begin = left;
int end = right;
int pivot = arr[right];
while (begin < end) {
while (begin < end && arr[begin] <= pivot){
begin++;
}
arr[end] = arr[begin];
while (begin < end && arr[end] >= pivot){
end--;
}
arr[begin] = arr[end];
}
arr[begin] = pivot;
return begin;
}
3、前后下标法
流程:
第一步:先用两个下标 div,i 指向数列的第一个元素,取最后一个元素作为基准值。
第二步:遍历整个数列,让 i 下标的值依次与基准值进行比较,如果小于等于基准值,那么交换div 和 i 所在值,并且 div 和 i 都向后移动,如果大于基准值,只让 i 向后移动即可,当整个数列遍历完后,将 div 所在值与基准值进行交换即可。此时的 div 就是中间位置。下面是遍历的流程。
代码如下:
int Partition_3(int arr[], int left, int right){ //前后下标
int div = left;
for (int i = left; i < right; i++){
if (arr[i] < arr[right]){
Swap(arr + i, arr + div);
div++;
}
}
Swap(arr + div, arr + right);
return div;
}
快速排序完整代码如下:
int Partition_1(int arr[], int left, int right){//hover法
int begin = left;
int end = right;
while (begin < end){
while (begin < end && arr[begin] <= arr[right]){
begin++;
}
while (begin < end && arr[end] >= arr[right]){
end--;
}
Swap(arr + begin, arr + end);
}
Swap(arr + begin, arr + right);
return begin;
}
int Partition_2(int arr[], int left, int right){ //挖坑法
int begin = left;
int end = right;
int pivot = arr[right];
while (begin < end) {
while (begin < end && arr[begin] <= pivot){
begin++;
}
arr[end] = arr[begin];
while (begin < end && arr[end] >= pivot){
end--;
}
arr[begin] = arr[end];
}
arr[begin] = pivot;
return begin;
}
int Partition_3(int arr[], int left, int right){ //前后下标
int div = left;
for (int i = left; i < right; i++){
if (arr[i] < arr[right]){
Swap(arr + i, arr + div);
div++;
}
}
Swap(arr + div, arr + right);
return div;
}
void __QuickSort(int arr[], int left, int right){
if (left == right){
//区间内只有一个数
return;
}
if (left > right){
//区间内没有数
return;
}
//基准值是 arr[right]
int div;
//用来保存最终基准值所在的下标
div = Partition_3(arr, left, right);
//遍历arr[left, right],把小的放左,大的放右,返回最后基准值所在的下标
//此时区间被分成了
//[left, div - 1] 比基准值小 [div, div]基准值 [div + 1, right]比基准值大
__QuickSort(arr, left, div - 1);
__QuickSort(arr, div + 1, right);
}
void QuickSort(int arr[], int size){
__QuickSort(arr, 0, size - 1);
}