快速排序-hoare版本
算法思路 :
创建左右指针,确定基准值
right
从右向左找出比基准值小的数据,left
从左向右找出比基准值大的数据,左右指针数据交换,进入下次循环
问题1:为什么跳出循环后
right
位置的值一定不大于key
?当
left > right
时,即right
走到left
的左侧,而left
扫描过的数据均不大于key
,因此right
此时指向的数据一定不大于key
问题2:为什么
left
和right
指定的数据和key
值相等时也要交换?相等的值参与交换确实有一些额外消耗。实际还有各种复杂的场景,假设数组中的数据大量重复时,无法进行有效的分割排序。
key
是基准值
例如:
6 1 2 7 9 3
key
指向6,left
指向1,right
指向3
left
从左向右找出比基准值大的数据,right
从右向左找出比基准值小的数据,左右指针数据交换,进入下次循环
left
指向7,right
指向3交换
left
和right
left
指向的数据7变成数据3,right
指向的数据3变成数据7
6 1 2 3 9 7
key
指向6,left
指向3,right
指向7
left
从左向右找出比基准值大的数据,right
从右向左找出比基准值小的数据,左右指针数据交换,进入下次循环
left
指向9,right
指向3此时
left>right
left > right
的时候,right
和基准值key
交换交换
key
和right
的数据3 1 2 6 9 7
然后返回基准值6
代码实现:
Sort.h
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include<stdlib.h>
#include<time.h>
//打印
void PrintArr(int* arr, int n);
//快速排序
//hoare版本
void QuickSort(int* arr, int left, int right);
Sort.c
#include"Sort.h"
//打印
void PrintArr(int* arr, int n)
{
for (int i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
//交换
void Swap(int* x, int* y)
{
int tmp = *x;
*x = *y;
*y = tmp;
}
//快速排序找基准值
int _QuickSort(int* arr, int left, int right)
{
int keyi = left;
++left;
while (left <= right)//left和right相遇的位置的值比基准值要大
{
//right找到比基准值小的
while (left <= right && arr[right] > arr[keyi])
{
right--;//right从右往左找比基准值keyi要小的,当前位置不满足就向前一位
}
//left找到比基准值大的
while (left <= right && arr[left] < arr[keyi])
{
left++;//left从左往右找比基准值keyi要大的,当前位置不满足就向后一位
}
//right和left互相交换
//因为left找到比基准值大的,right找到比基准值小的
//left比right小的时候,自然要交换数据
if (left <= right)
{
Swap(&arr[left++], &arr[right--]);
}
}
//left > right的时候,right和基准值keyi交换
Swap(&arr[keyi], &arr[right]);
return right;//返回基准值
}
//快速排序
void QuickSort(int* arr, int left, int right)
{
if (left >= right)
{
return;
}
//[left,right]--->找基准值keyi
int keyi = _QuickSort(arr, left, right);
//左子序列:[left,keyi-1]
QuickSort(arr, left, keyi - 1);
//右子序列:[keyi+1,right]
QuickSort(arr, keyi + 1, right);
}
test.c
#include"Sort.h"
int main()
{
int a[] = { 5, 3, 9, 6, 2, 4, 7, 1, 8 };
int n = sizeof(a) / sizeof(int);
printf("排序前:");
PrintArr(a, n);
QuickSort(a, 0, n - 1);
printf("排序后:");
PrintArr(a, n);
return 0;
}