今天来讲下快速排序的实现逻辑和代码。
逻辑:
1.首先选取一个无序序列的某个数值作为中值prvot;
2.将大于prvot的数值排放在prvot的右边,小于i的放左边;
3.将prvot左侧和右侧的数值再次进行排放,直到个数为1.
到这时排序也就结束了;
这个排序体现了什么思想呢?——————就是分治和递归。
为了方便代码的实现,我们现在每次都把第一个数值作为prvot;
1.先写出主函数
int main()
{
int arr[1000] = { 0 }, n,i;
scanf("%d",&n); //数组大小
for (i = 0; i < n; i++)
{
scanf("%d", &arr[i]); //进行输入
}
quick(arr, 0, n-1); //进行排序
for (i = 0; i < n; i++)
printf("%d ", arr[i]); //输出结果
return 0;
}
2.快速排序的基本逻辑:
我们先只看单次排序:
我们任意拿五个数
定义一个变量prvot,将首个数值放进prvot,然后我们默认首个位置是没有数值的,这样便于观察理解,反正值是会改变的,不会影响代码的实现。
顺便再在首尾定义两个指针,便于改变数值,首先从R开始比较,5>3所以我们不动5,再将R向左移动
这时我们发现1<3,那么我们将1放入最左边,并且将L向右移动(因为L的位置与5一样,是排过序的)。
交换对比的指针。现在从L边看起、
发现8>3,所以我们把8放在R所指的位置,并将R向左移动。
重复进行比较我们会发现L总会和R重合。
然后把prvot的值赋在该处。
再对左右两侧进行排序,直到个数为1,就像图中左侧只有1了,是最小的不用排序,右侧的数值未处理,需要再次排序。
这是单次排序的代码
void quick(int arr[], int left, int right)
{
int prvot = arr[left], flag = 1; // prvot放中轴值,flag来切换指针的运动
int* L = &arr[left], * R = &arr[right];
while (L < R)
{
if (flag)
{
if (*R >= prvot)
R--;
else
{
*L = *R;
L++;
flag = 0;
}
}
else
{
if (*L <= prvot)
L++;
else
{
*R = *L;
R--;
flag = 1;
}
}
}
*L = prvot;
}
我们现在需要再次进行排序,直到个数为一,我们就此出发进行编写。
int i;
for (i = 0; i < right; i++)
if (arr[i] == prvot)
break; //寻找中轴值的下标
quick(arr, left, i - 1); //对两边进行排序
quick(arr, i + 1, right);
最后我们需要设置停止的条件,我们知道要让个数为1,就意味着让quick中的left>right(注意是大于不是等于应为再函数运行完后我们传参传的是i-1,最后两边是无法等于的)
if (left > right)
return;
最后拼接修改起来就是
#define maxn 100
#include<stdio.h>
void quick(int arr[], int left, int right)
{
if (left > right)
return;
int prvot = arr[left], flag = 1, i;
int* L = &arr[left], * R = &arr[right];
while (L < R)
{
if (flag)
{
if (*R >= prvot)
R--;
else
{
*L = *R;
L++;
flag = 0;
}
}
else
{
if (*L <= prvot)
L++;
else
{
*R = *L;
R--;
flag = 1;
}
}
}
*L = prvot;
for (i = 0; i < right; i++)
if (arr[i] == prvot)
break;
quick(arr, left, i - 1);
quick(arr, i + 1, right);
}
int main()
{
int arr[maxn] = { 0 }, n,i;
scanf("%d",&n);
for (i = 0; i < n; i++)
{
scanf("%d", &arr[i]);
}
quick(arr, 0, n-1);
for (i = 0; i < n; i++)
printf("%d ", arr[i]);
return 0;
}