前言:阿里嘎多,好久没更新了,是时候写一篇博客来让无聊的生活泛泛涟漪
一、算法逻辑
首先要明确一点,“1 2 3 4 5 6 7 8 9”这样一个按照升序排列的数组中,随便拿出一个数字,前面的都比该数字小,后面的都比该数字大。在此基础上,我们可以得到快排的逻辑:
选择一个基础值作为中间数,然后选定两个指针分别从前往后和从后往前寻找,先让一个左指针从前往后寻找,当指针指到的数大于基准数时暂停,从另一个右指针从后往前寻找,当选定的数字比基准数小时暂停,然后让两个指针所指的数字互换位置。
互换位置后,如果左指针和右指针仍然分别在基准值的前面和后面,那么两个指针继续寻找。如果已经不满足前面的条件则说明比基准值小的数字已经都在前面,比基准值大的数字已经全都在后面。所以分别对基准值前面和后面的数字进行递归
二、代码实现
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void swap(int* a, int* b)
{
int temp = *a;
*a = *b;
*b = temp;
}//构造一个函数使得两个指针所指的位置可以互换
//快速排序函数
void sortquick(int arr[], int L, int R)
{
if (L >= R) //这个if语句一般留给递归,如果前面的比后面小,则结束本次函数
return;
int left = L-1;//左指针
int right = R+1;//右指针
int pivot = arr[(L+R)>>1];//选定基准值,其中左右指针分别加一和减一是为了和下面的do while进行配合
while (left < right)//用while循环
{
do {
left++;
} while (arr[left] < pivot);//如果在左右指针选定基准值的过程中选用while循环,如果pivot=arr[left]=arr[right]就会陷入死循环。
do {
right--;
} while (arr[right] > pivot);
if (left < right) {
swap(&arr[left], &arr[right]);
}
}
sortquick(arr, L, right);//依次递归划分的左区间,直至区间长度为1为止
sortquick(arr, right + 1, R);//递归划分的右区间
}
int main()
{
int n;
scanf("%d ", &n);
int arr[100005];
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
} //初始化数组
sortquick(arr, 0, n - 1); //将数组、0和数组中末尾元素传给sortquick函数
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
return 0;
}
这里尤其注意的是里面采用了do while循环给左右两个指针而不是while。如果arr[left]=arr[right]=pivot,那么下面的swap函数仍然可以执行,但是本质上相同的数字交换位置,就等于没有交换,那么就会陷入死循环。do while先判断后加一,可以保证在相等时继续向后遍历。