快速排序的核心思想:
就是选择一个参考值key(一般是第一个元素),将key通过快速排序逻辑放在一个左边都是比他小的数且右边都是比他大的数的位置上,具体实现思路如下:
-
定义begin和 end 两个哨兵分别在队头和队尾,用 i 和 j 记录头尾移动坐标;i++ 过程中发现比 key大的元素、end-- 过程中发现比key小的元素停下,交换arr[i] arr[j]值,然后继续相向而行;
-
直至 i >= j 停止; 这时 交换 key 和arr[i];此时的key 左边全是比他小的且右边全是比他大的,它的位置就此固定!
-
以上是单趟的情况;那么整体如果排序呢?
-
运用递归的思路,通过第一趟已经确定了一个知道自己位置的数,这个数也将整个数组划分楚河汉界,左侧 区间(begin ~ i );右侧 区间 (i+1 ~ end);
-
如果在左侧调用快速排序函数, 那么(begin ~ i )区间必然也会为首元素选择出一个它的位置,并划分区间,它的右侧依然是i+1 ~ end;这里的end就是 i , i+1 就是 选出的元素位置的下一个;是不是就又开始重复套娃了,左边套完,接着去右边 直至数组左侧全部有序之后,开始右侧,右侧来一趟又会划分左右,这时继续调用我们的左右快速函数即可。
-
所有,冗余的话说了这么多,归根结底就是 按照左右区间,重复调用这个函数;另外递归的终止条件为,begin >= end;
#include<stdio.h>
void QuickSort(int* arr, int begin, int end);
void swap(int* p1, int* p2) {
int tem = *p1;
*p1 = *p2;
*p2 = tem;
}
void print(int* p3 , int sz) {
for (size_t i = 0; i < sz; i++)
{
printf("%d ",p3[i]);
}
}
void main() {
//单趟情况
int arr[10] = {6,1,2,7,9,3,4,5,10,8};
//定义开始和结束下标
int begin = 0;
int n = sizeof(arr) / sizeof(int);
int end = n-1;
QuickSort(arr,begin,end);
print(arr , n);
}
void QuickSort(int* arr,int begin,int end) {
if (begin >= end) {
return;
}
int i = begin;
int key = arr[begin];
int j = end;
while (i != j)
{
//找到值,停下J
while (arr[j]>key && j > i)
{
j--;
}
//找到值,停下I
while (arr[i] <= key && j > i)
{
i++;
}
//交换 arr[i] arr[j]
swap(&arr[i],&arr[j]);
}
//相遇
swap(&arr[i], &arr[begin]);
//i这个点的值 确定好了;
//关注i左 和i右
QuickSort(arr, begin, i-1);
QuickSort(arr, i+1 , end);
}
单趟结果:
可以发现 首元素 6 左侧全是比他小的 && 右侧全是比他大的 ;
整体测试结果: