快排的的原理
//方案一:直接插入排序
/*
void InsertSort1(int arr[], int s, int l)
{
for(int i = s; i < l+1; ++i)
{
int index = arr[i];//记录下要对比的数
int j = i - 1;//对比前一个数
while(j > -1 && index < arr[j])
{
//不匹配把数字向后移动
arr[i--] = arr[j--];
}
arr[j+1] = index;
}
}
*/
//方案二:三数取中(0,mid,end)放基准值位
void Swap(int arr[], int swap1, int swap2)
{
int tmp = arr[swap1];
arr[swap1] = arr[swap2];
arr[swap2] = tmp;
}
void GetMidNum(int arr[], int left, int midd, int right)
{
//使得最后三数的位置是 前(中数) 中(小数) 后(大数)
if(arr[midd] > arr[left])
Swap(arr, midd, left);
if(arr[midd] > arr[right])
Swap(arr, midd, right);
if(arr[left] > arr[right])
Swap(arr, left, right);
}
int Partition(int arr[], int s, int l)//将数组分区
{
int tmp = arr[s];//拿到基准值
while(s < l)
{
while(s < l && arr[l] >= tmp) l--;//否则就去覆盖前面的数值
arr[s] = arr[l];
while(s < l && arr[s] <= tmp) s++;//同上
arr[l] = arr[s];
}//记得把基准值放到他的位置
arr[s] = tmp;
return s;
}
//递归实现
void Quick(int arr[], int s, int l)
{
if(s < l)
{
//方案一 直接插排
/*
if(l - s + 1 <= 20)
{
InsertSort1(arr, s, l);
}
*/
//方案二:三数取中放基准值位
/*
int mid = (l - s)/2 + s;
GetMidNum(arr, s, mid, l);
*/
//方案三:随机取基准值
//Swap(arr, s, rand() % (l - s + 1) + s);
int boundindex = Partition(arr, s, l);
Quick(arr, s, boundindex-1);
Quick(arr, boundindex+1, l);
}
}
//非递归实现
void Quick2(int arr[], int s, int l)
{
stack<int> st;
if(s < l)
{
st.push(s);
st.push(l);
while(!st.empty())
{
int high = st.top();
st.pop();
int low = st.top();
st.pop();
int boundindex = Partition(arr, low, high);
if(low < boundindex - 1)
{
st.push(low);//有至少两个数
st.push(boundindex-1);
}
if(high > boundindex+1)
{
st.push(boundindex+1);
st.push(high);
}
}
}
}
void QuickSort(int arr[], int len)
{
Quick(arr, 0, len-1);//递归
//Quick2(arr, 0, len-1);//非递归
}
优化方案:主要是在Quick上做手脚,以此来体现快
1、当分裂到一定数量时,用直接插排来提高效率
2、三数取中,生成基准值
3、随机生成基准值