快速排序:
图解大体思想:
可以看到,最后的数据中:绿色都是小于等于6的数据;蓝色就是大于6 的数据;接着分别对绿色,蓝色部分进行同样的方式,最终就会排序完成。
确定快速排序的流程:
划分区间的方法:
- Hover方法
图解思想:
Hover版本的代码:
//Hover法
int Hover(int array[], int right, int left) { //left,right是数据的下标
int begin = left;
int end = right;
//基准值是array[right] //选择区间的最右边的数据作为基准值
while (begin < end) { //终止条件
if (begin<end&&array[begin]<=array[right]) { //左边值小于等于右边的值
begin++;
}
//这时候就卡住了,就走右边
if (begin<end&&array[end]>=array[right]) {
end++;
}
Swap(array + begin, array + end);
}
//区间被分成小,基准,大
Swap(array + begin, array + right);
//返回当前基准值
return array[right];
}
- 挖坑法
挖坑法图解思想:
挖坑法的代码:
//挖坑法
//时间复杂度 O(1)
int Hole(int array[], int left, int right) {
//left right 是数组的下标
int begin = left;
int end = right;
int hole = array[right]; //基准值
while (begin < end) { //优先走左边
while (begin < end&&array[begin] <= hole) {
begin++;
}
//卡住了,填坑
array[end] = array[begin];
//走右边
while (begin < end&&array[end] >= hole) {
end++;
}
//右边也卡住了
array[begin] = array[end];
}
//区间被分成小,大,基准
Swap(array + begin, &hole);
//返回当前基准值
return array[right];
}
- 前后下标法
前后下标法的代码:
//前后下标法
int BeforeAfter(int array[], int left, int right)//left right 是数组的下标
{
int i = left;
int d = left;
while (i != right) { //i先走
while (array[i] >= array[right]) { //i停止条件
i++;
}
//交换array[i],array[d]
Swap(array + d, array + i);
i++;
d++;
}
Swap(array + d, array + i);
//返回当前基准值
return array[right];
/*
//for循环的
for (int i = left; i < right; i++) {
if (array[i] < array[right]) {
Swap(array + d, array + i);
d++;
}
}
Swap(array + d, array + i);
//返回当前基准值
return array[right];
*/
}
选合适的下标:采用三数取中法
三数取中法:
三数取中的代码:
//三数取中方法,返回合适的下标
int PickMid(int array[], int left, int right) {
int mid = (left + right) / 2;
if (array[left] > array[right] && array[left] > array[mid]) {
if (array[mid] > array[right]) {
return mid;
}
else {
return right;
}
}
else if (array[mid] > array[right]) {
if (array[left] > array[right]) {
return left;
}
else {
return right;
}
}
else
if (array[mid] > array[left]) {
return mid;
}
else {
return left;
}
}
已知之前的,就可以写完整的快排代码:
//空间复杂度 log n --- n
//递归调用的深度 (二叉树的高度)
void QuickSort(int array[], int left, int right) {
//基本以右边为基准
//终止条件 size==1 || size ==0
//left==right 剩余一个数
//left>right 区间内没有数
if (left == right) {
return;
}
if (left == right) {
return;
}
//选三个数取中
int pivot_index = PickMid(array, left, right);
Swap(array + pivot_index, array + right);
// 基准值所在下标
int div; // 比基准值小的数放到基准值左侧 比基准值大的数放到基准值右侧
//三种方法
div = Hover(array, left, right); //遍历array[left,right],把小的放左,大的放右边
//div = Hole(array, left, right); //遍历array[left,right],把小的放左,大的放右边
//div = BeforeAfter(array, left, right); //遍历array[left,right],把小的放左,大的放右边
//类似二叉树的前序遍历
QuickSort(array, left, div - 1); //分治算法
QuickSort(array, div + 1, right);
}