//快速排序
//每一趟将待排序以基准值为中心分成俩部分,左边部分的都小于基准值 右边部分的值,然后对其俩边部分再进行同样的处理即可
//怎么将数据以基准值中心划分分成俩部分
//方法1 借助辅助空间
//方法2 不借助辅助空间(挖空法)
//数据越快 反而效率越高
//数据越有序 反而效率低
//快速排序的优化:(怎么把数据打乱).
//1 快排刚刚启动时,如果待排序数据数据量较小,直接去调用直接插入 / 冒泡排序
//2.快排运行途中时,如果发现划分出来的小组里而的数量量小于一定的值,则直接调用直接插入
//3.三数取中法(取出范围内最左端值,最右端值,中间值这三个值,然后把不大不小的那个值放到最左端一会当基准值去用)
//4.随机数法(随机从里面取值,然后交换,执行多次这个操作即可)
//单次划分,用的方法是挖空法 (Partition)
int Partition(int arr[], int left, int right)
{
//1.先讲最左端的值,取出用tmp保存,防止一会被覆盖
int tmp = arr[left];
//2.进入while循环,条件是left没有和right相遇
while (left < right)
{
//3.先从右向左找,找一个比基准值小于或者等于的值,找到后扔到左边空位上
while (left<right && arr[right] > tmp)
right--;
//这个内部while循环结束,只会有两种可能性:
//可能1:随着right--,两个指针相遇了
//可能2:两个指针还没有相遇,但是确实找到了一个小于等于tmp的值,由此时的right指向
if (left == right)
{
break;
}
arr[left] = arr[right];
//4.再从左向右找,找一个比基准值大于的值,找到后扔到右边空位上
while (left < right && arr[left] <= tmp)
left++;
if (left == right)
{
break;
}
arr[right] = arr[left];
}
//5.当while循环结束,表示left和right相遇了,此时就可以将tmp保存的基准值放回去了
arr[left] = tmp;//arr[right]=tmp;
return left; //return right
}
/*int Partition(int arr[], int left, int right)
{
int tmp = arr[left];
while (left < right)
{
while (left<right && arr[right]>tmp)
right--;
if (left == right)
break;
arr[right] = arr[left];
}
arr[left] = tmp;
return left*/;
}
//时间复杂度O(nlogn) 空间复杂度O(logn) 稳定性:不稳定
void Quick(int arr[], int left, int right)
{
//挖空法 (Partition)
//left = right 只有一个值
//left < right 不止一个值(>=2)
//left > right 一个值都没有
if (left >= right)
{
return;
}
int par = Partition(arr, left, right);
Quick(arr, left, par - 1);
Quick(arr, par + 1, right);
}
//void Quick(int arr[], int left, int right)
//{
// if (left >= right)
// {
// return;
// }
// int par = Partition(arr, left, right);
// Quick(arr, left, par - 1);
// Quick(arr, par + 1, right);
//}
//快速排序
void Quick_Sort(int arr[], int len) //递归的方式
{
Quick(arr, 0, len - 1);
}
//void Quick_Sort(int arr[].int len)
//{
// Quick(arr.0,len - 1);
//}
#include <stack>
//快速排序
void Quick_Sort_No_Recursion(int arr[], int len) //非递归的方式
{
std::stack<int> st;//因为是左右边界 所以入栈一次两个值 出栈也一次两个值
st.push(0);
st.push(len - 1);
while (!st.empty())
{
int right = st.top();
st.pop();
int left = st.top();
st.pop();
int par = Partition(arr, left, right);//[left, par-1] par [par+1, right]
if (left < par - 1)//[left, par-1]
{
st.push(left);
st.push(par - 1);
}
if (par + 1 < right)//[par+1, right]
{
st.push(par + 1);
st.push(right);
}
}
}