快速排序
给定一个序列:
22 33 49 47 33' 12 68 29
进行快速排序
主要思想
从序列中,任选一个记录k作为轴值pivot选择策略:第一个元素最后一个元素中间元素随机选择将剩余的元素,分割成 左子序列 L 和 右子序列 RL 中所有元素都 < k, R 中所有元素都 > k对 L 和 R递归进行快排,直到子序列中有 0 个 或者 1 个元素,退出图解
初始数组:选定47为轴值pivot
pivot与最后一个值29进行交换()
接下来,以pivot=47为界,分成左子序列L和右子序列R比47大的都放在右边,比47小的都放在左边(用的交换)
遍历数组
两个指针left和right当left != right的时候如果left和right未相遇。把right的值赋给left对应的值arr[left] = arr[right]right指针停止移动,轮到left移动如果left和right未相遇,把left的值赋给right对应的值arr[right] = arr[left]left指针停止移动,轮到right移动若arr[left]的,小于等于pivot,且left < right的时候,left右移当arr[right]的值,大于等于pivot,且right > left的时候,right左移注意:轴值用pivot保存第一轮分割序列
pivot=47和最后一个值互换
22 <= 47,left向右移动
33 <= 47,left向右移动
49 > 47,不满足arr[left] <= pivot把left的值赋给right
arr[right] = arr[left]
赋值过后,left不动,right向左移动
68 >= 47,right向左移动
12 < 47,不满足arr[right] >= pivot把right的值赋给left
arr[left] = arr[right]
赋值过后,right不动,left向右移动
29 < 47,left向右移动
33' < 47,left向右移动
向右移动后,left == right,退出循环将pivot赋给arr[left]
至此,第一轮分割序列完成
第二轮分割序列 --- 左子序列
经过第一轮分割,47左边的是左子序列,右边是右子序列
第二轮对左子序列分割,选择中间值作为pivot
12和33'进行交换
22 > 12,不满足arr[left] <= pivot把arr[left]赋给arr[right]
arr[right] = arr[left]
赋值过后,left不动,right向左移动
29、33'、33都比12大,所以right一直移动到下图位置
33 > 12,right继续向左移动
此时right == left,终止循环把pivot赋给arr[left]
至此,左子序列1也分割完成了
小结
快排就是一个递归的过程,分割得到左子序列
再对左子序列进行快排分割,得到左子序列的左子序列....
处理完左边,再去处理右边的右子序列
第三轮分割序列 --- 右子序列
右子序列只有47、68、49,选择48作为轴值 pivot
pivot和最后一个值交换
47、49都比pivot=68小,left一直向右移动,直到left == right
分割之后,只剩下左子序列:47、49
47、49,选49作为轴值,得到左子序列47子序列只剩下一个元素47,就不必排序了,右边排序结束
结果:47、49、68
C++实现
选择中间的值作为轴值
总结