思想
- 快速排序之所以快,一个重要原因就是其每一次遍历,都把本轮要排序的数字(称为轴)放到了最终的位置上
- 快排使用分治思想,所以一般采用递归实现,非递归版本可以用栈
- 根据第一点,我们需要一个函数 Partition,用于快速排序中获得轴的最终位置
- 根据第二点,在一次遍历中两次递归调用排序函数,输入轴两边的序列进行排序即可
代码
- 快速排序本体函数:
//快速排序的本体函数
void QuickSort(int arr[], int low, int high)
{if(low<high){int pivotpos = Partition(arr, low, high);QuickSort(arr, low, pivotpos-1);QuickSort(arr, pivotpos+1, high);}
}
- 获得轴位置的函数
//此函数用于快速排序中获得轴的最终位置
int Partition(int arr[], int low, int high)
{int pivot = arr[low];while(low<high){//指针碰撞时轴的左右子序列都排序完成while(low<high && arr[high]>=pivot) high--;arr[low] = arr[high];while(low<high && arr[low]<=pivot) low++;arr[high] = arr[low];}arr[low] = pivot;return low;
}
要点
其中,Partition 很重要,有几个书写的要点:
- 在外循环中指针碰撞时视为排序完成
- 内循环中,由于两个指针在遍历时可能会越界,故需检测是否碰撞
- 如果轴选择了 low 处的元素,那么 low 处可以视为空闲,所以此时要从 high 处开始遍历,直到找到需要放在轴左边的元素为止,将这个元素放入 low 处
- high 处的元素放到 low 处后,high 处可以视为空闲,此时从 low 处开始遍历,直到找到应该放在轴右边的元素,将其插入 high 处
- 指针碰撞后,low == high,将轴放到指针碰撞的位置,并返回此时轴的位置