正确性说明:一个排好序的序列(此处不妨设递增的序列)一定是符合如下特点:
“分成两部分,前面的部分一定每个数字都大于后面的部分”
对于两个部分中的各个部分,继续分成两半,一定也符合“分成两半,前面的部分的每个数字一定都大于后面的部分”,一直到终止状态,也就是最简单的序列—只有两个数字的时候
至此,我们说明完了快速排序的正确性:
换句话说,
①我们可以通过每次都将序列分解成为两部分,保证前面部分大于后面部分
②然后对于各个部分同样分成两个部分,保证前面部分大于后面部分
③一直到序列只剩下两个数字的时候停下
这样的序列一定就是排好序的
如何实现:
①首先确定一个标准mid
②小于等于这个标准的放到前面,大于等于这个标准的放到后面(注意了,等于的话放到前面和放到后面都是没有关系的,我们这里说的是非常严谨的)
③然后递归处理左右两边
(默认大家第一次接触算法:这里简单稍微介绍一下什么叫做递归处理左右两边,就是先处理左边,然后处理左边的左边,一直到剩下一个数字,然后处理上一次遗留下的右边,直至处理完成刚开始剩下的右边)这个过程可能看起来稍显复杂,但是计算机可以自动帮我们实现这个过程,如果按照递归的方式写了代码,计算机就会一直实现下去,然后标记好每一步遗留下的问题,等走到最深的的一步,再回头来处理
计算机实现方式:
一个显而易见的实现方式是:
①确定一个标准
②用两个数组,第一个放小于等于标准的数的数,一个放上大于等于标准的数,然后先把第一个数组里面的数字放到数组,然后把 第二个数组里面的数字放到数组里面,
③递归处理左边右边
这里分享一个绝佳的实现方式:双指针
我们仅仅需要一遍扫描:
int mid=q[(l+r)/2],i=l-1,j=r+1;
while(i<j){
do ++i; while(q[i]<mid);
do --j; while(q[j]>mid);
if(i<j) swap(q[i],q[j]);
}
这样就能实现对某一段序列小于等于标准数字的放到前面,大于等于标准数字的放到后面,同时指针自然而然的将序列分成了两个部分:
//对于样例 3 1 2 4 5而言,经过上述代码i = 2,j = 1
//对于样例2 2 2 3 4 而言,i == j
//序列被分成了两个部分,一个部分是l j,另一个是j + 1 r或者说l i - 1,另一个是i到r
注意代码中是严格小于大于,并没有等号,但是我们却实现了小于等于的在前面,大于等于的后面