先找一个标准值,将小于标准值的放在左侧,大于标准值的放在右侧,两边再重复此操作
快排是分治的经典应用
1.找个标准值(枢轴)
2.将标准值保存
3.从右向左找比标准值小的放入左侧坑
从左向右找比标准值大的放入右侧坑
重复此过程直到相遇
4.放入标准值到相遇的位置
5.对左右两部分做相同的处理
int Sort(int* arr, int begin, int end) {
int temp = arr[begin];//保存标准值
//遍历
while (begin<end)
{
//从右向左找比标准值小的位置
while (end > begin) {
if (arr[end] < temp) {
//填入左侧坑,此时是begin在标记
arr[begin] = arr[end];
begin++;
break;
}
end--;
}
//从左向右找比标准值大的位置
while ( begin < end) {
if (arr[begin] > temp) {
//填入右侧坑,此时是end在标记
arr[end] = arr[begin];
end--;
break;
}
begin++;
}
}
//填入标准值
arr[begin] = temp;
return begin;//返回标准值位置
}
void QuickSort(int* arr, int begin, int end) {
if (arr == NULL || begin >= end)return;
//标准值位置
int nStandard;
nStandard = Sort(arr, begin, end);
//分割
QuickSort(arr, begin, nStandard - 1);
QuickSort(arr, nStandard +1, end);
}
区间分割法
1.定义一个small边界,初值为begin-1 定义一个标准值为数组最后一个元素arr[end]
2.遍历数组,如果数组元素比标准值小: 小区间扩张,arr[small+1]与arr[i]当前值进行交换
3.遍历结束后把标准值放在small+1的位置上
int Sort2(int* arr, int begin, int end) {
int small = begin - 1;//小区间边界从begin-1开始
for (begin; begin < end; begin++) {
//遍历数组如果比标准值小,让那个i位置的值与小区间边界+1位置的值交换,边界偏移
if (arr[begin] < arr[end]) {//标准值为最后一个数arr[end]
if (++small != begin) {//异或交换时如果对同一个变量交换会把这个变量变为0
arr[small] ^= arr[begin];
arr[begin] ^= arr[small];
arr[small] ^= arr[begin];
}
}
}
//最后将标准值也放入
if (++small != end) {//异或交换时如果对同一个变量交换会把这个变量变为0
arr[small] ^= arr[end];
arr[end] ^= arr[small];
arr[small] ^= arr[end];
}
return small;
}
void QuickSort(int* arr, int begin, int end) {
if (arr == NULL || begin >= end)return;
//标准值位置
int nStandard;
nStandard = Sort2(arr, begin, end);
//分割,同样方法处理标准值的左边和右边
QuickSort(arr, begin, nStandard - 1);
QuickSort(arr, nStandard +1, end);
}
快排的其他优化方法
标准值选择 3选1 9选1
标准值聚集,可以把与标准值相同的放到最左或最右,最后再与标准值的左或右边交换
当元素数量小于16的时候改用插入排序
循环+堆空间 代替 递归 (减少崩溃可能性)
尾递归