快速排序:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的数据比另一部分记录的关键字小,则分别可对这两部分数据进行继续排序,以达到整个序列有序。
快速排序有三个版本:
1.hoare版本
示图:
代码:hoare版本
int _QuickSort_1(int *arr, int left, int right)//hoare版本
{
int tmp = arr[left];//基准值
while (left < right)
{
while (left < right && tmp < arr[right])
right--;
Swap(&arr[left], &arr[right]);
while (left < right && tmp >= arr[left])
left++;
Swap(&arr[left],&arr[right]);
}
return left;
}
void QuickSort(int *arr, int left, int right)
{
if (left >= right)
return;
int end = _QuickSort_1(arr, left, right - 1);
QuickSort(arr, left, end);
QuickSort(arr, end + 1, right);
}
2.挖坑法
排序需要两个操作:
- 数据比较
- 数据交换
挖坑法是通过减少对数据的交换来达到排序。
代码:挖坑法
int _QuickSort_2(int *arr, int left, int right)//挖坑法
{
int tmp = arr[left];
while (left < right)
{
while (left < right && tmp < arr[right])
right--;
arr[left] = arr[right];
while (left < right && tmp >= arr[left])
left++;
arr[right] = arr[left];
}
arr[left] = tmp;//tmp的值,一定要放到最后的空间中
return left;
}
void QuickSort(int *arr, int left, int right)
{
if (left >= right)
return;
int end = _QuickSort_2(arr, left, right - 1);
QuickSort(arr, left, end);
QuickSort(arr, end + 1, right);
}
3.双指针法
通过设置快慢指针的方法来达到排序。
算法步骤::
- 设置两个指针pos,forward
- forward处值小于基准值,pos++,如果pos≠forward,将两者值交换
- foward处值大于基准值,pos不动
- 最后pos的值和起始位置值交换,返回pos
代码:双指针法
int _QuickSort_3(int *arr, int left, int right)//双指针法
{
int tmp = arr[left];//基准值
int pos = left;
int forward = left;
for (forward; forward <= right; ++forward)
{
if (arr[forward] < tmp)//小于是做升序,大于做降序
{
pos++;
if (pos != forward)
{
Swap(&arr[forward], &arr[pos]);
}
}
}
Swap(&arr[left], &arr[pos]);
return pos;
}
void QuickSort(int *arr, int left, int right)
{
if (left >= right)
return;
int end = _QuickSort_3(arr, left, right - 1);
QuickSort(arr, left, end);
QuickSort(arr, end + 1, right);
}
4.优化方法
快速排序有一些待改进的地方。
若:起始位置为最大或者最小时,排序的效率并不高,故采用三路折中法对算法进行改进。
分别对:起始位置,中间位置,末尾位置进行比较,选取中间值进行排序。
int GetMidValue(int *arr, int left, int right)//三路折中法
{
int mid = (left + right) / 2;
if (arr[mid] > arr[left] && arr[mid] < arr[right])
return mid;
else if (arr[mid] < arr[left] && arr[left] < arr[right])
return left;
return right;
}
数据长度在5~25之间的时候,算法效率没有直接插入快(出自殷人昆教授的数据结构教材)。