1.快速排序的原理:
快速排序是先任取数组中的一个元素作为基准值(一般是首或者尾),遍历一遍数组,让比大的在其右边,比他小的在其左边,这样就完成了基准值的定位,再将其右边和左边的分别重复上操作,完成排序。
2.前后指针法:
先定义数组开头是begin,结尾是end。end向左找比key小的数,找到就停止,begin向右找比key大的数找到就停止,最后交换end和begin的数据。当end=begin时就和key交换数据。
3.左右指针法
定义头数据位置为prev,第二个数据位置为cur,头数据为key。cur向右找比key小的数据,找到后停止,与++prev位置交换数据,然后++cur。循环上述操作,当cur跳出循环时,key与prev位置交换数据.
4.快排的优化
4.1三数取中
当数组中的数据是有序的时候,快排的效率最低,因为每次取的key都是最大或者最小值,这样他排出的位置是边缘位置,效率极低,我们只需要取出数组左位置,右位置,中间位置中数据的中值,与左位置处交换,这样我们的key值就不会排到边缘位置
4.2小区间优化
这里我们介绍的快排都是递归形式的,其实递归越到后面占据的时间越多,在最后的几个小区间就要占据大部分时间来递归。我们这里拿500个数据举例子,其实后面的小区间递归占据了大部分时间
如果数据是1w或者100w个,那么最后的小区间如果还用递归的话,就大幅度增加了运行时间,其实最后的小区间我们可以直接采用简单的不需要递归的插入排序替我们完成,这样就可以大幅度减少时间
5.代码
void InsertSort(int* a, int n)
{
//假设【0-end】有序,将第end+1的数插排入【0-end+1】 0-(n-1)
for (int i = 0; i < n - 1; i++)
{
int end = i;
int tmp = a[end + 1];
while (end >= 0)
{
if (a[end] > tmp)
{
a[end + 1] = a[end];
--end;
}
else
{
break;
}
}
a[end + 1] = tmp;
}
}
void Swap(int* a1, int* a2)
{
int tmp = *a1;
*a1 = *a2;
*a2 = tmp;
}
int MidIndex(int* arr, int left, int right)
{
int mid = (left + right) / 2;
if (arr[left] < arr[mid])
{
if (arr[mid] < arr[right])
{
return mid;
}
else
{
return arr[left] < arr[right] ? right : left;
}
}
else//left > mid
{
if (arr[right] < arr[mid])
{
return mid;
}
else
{
return arr[left] < arr[right] ? left : right;
}
}
}
int _PartSort(int* arr, int left, int right)//挖坑法
{
int begin = left;
int end = right;
int key = arr[begin];
int pivot = begin;
while (begin < end)
{
while (begin < end && arr[end] >= key)
{
end--;
}
arr[pivot] = arr[end];
pivot = end;
while (begin < end && arr[begin] <= key)
{
begin++;
}
arr[pivot] = arr[begin];
pivot = begin;
}
pivot = begin;
arr[pivot] = key;
return pivot;
}
int _PartSort1(int* arr, int left, int right)//左右指针法
{
int keyi = left;
int begin = left;
int end = right;
while (begin < end)
{
while (begin < end && arr[end] >= arr[keyi])
{
end--;
}
while (begin < end && arr[begin] <= arr[keyi])
{
begin++;
}
Swap(&arr[begin], &arr[end]);
}
Swap(&arr[begin], &arr[keyi]);
return begin;
}
//前后指针法
int _PartSort2(int* arr, int left, int right)
{
int keyi = left;
int rev = left;
int cur = left + 1;
while (cur <= right)
{
if (arr[cur] < arr[keyi] && cur != (rev + 1))
{
Swap(&arr[cur], &arr[++rev]);
}
++cur;
}
Swap(&arr[keyi], &arr[rev]);
return rev;
}
void QuickSort(int* arr, int left, int right)
{
if (left > right)
{
return;
}
int index = MidIndex(arr, left, right); // 三数取中
Swap(&arr[index], &arr[left]);
int pivot = _PartSort2(arr, left, right);
if (pivot - 1 - left + 1 > 10)//进行小区间分出去排序
{
QuickSort(arr, left, pivot - 1);
}
else
{
InsertSort(arr + left, pivot - 1 - left + 1);
}
if (right - pivot - 1 + 1 > 10)
{
QuickSort(arr, pivot + 1, right);
}
else
{
InsertSort(arr + pivot + 1, right - pivot - 1 + 1);
}
}
6.扩展:
用数据结构的栈模拟实现快排的递归