坑人快排的救赎
参考代码
1 |
|
步骤讲解
设基准为$ povit = a[l] $ , $ i = l , j = r $
先从右端$(j)$开始,向左移动,直到$a[j] < povit $ , 交换$ a[i] , a[j]$ 。
再从左端$ (i)$开始,向右移动,直到$a[i] > povit $ , 交换$ a[i] , a[j]$ 。
不停重复,直到 $ i = j $停下。
先不停向左边重复,计算完左边再计算右边。
老师例题讲解
初始序列
{501, 89, 512, 61, 90, 908, 170, 897, 276, 653, 462}
第1趟排序(pivot=501)
当前处理区间:[0,10] ➔ {501, 89, 512, 61, 90, 908, 170, 897, 276, 653, 462}
从右找<501:
- j=10 : 462<501 → 交换0和10
{462, 89, 512, 61, 90, 908, 170, 897, 276, 653, 501}
- j=10 : 462<501 → 交换0和10
从左找>501:
- i=2 : 512>501 → 交换2和10
{462, 89, 501, 61, 90, 908, 170, 897, 276, 653, 512}
- i=2 : 512>501 → 交换2和10
从右找<501:
- j=8 : 276<501 → 交换2和8
{462, 89, 276, 61, 90, 908, 170, 897, 501, 653, 512}
- j=8 : 276<501 → 交换2和8
从左找>501:
- i=5 : 908>501 → 交换5和8
{462, 89, 276, 61, 90, 501, 170, 897, 908, 653, 512}
- i=5 : 908>501 → 交换5和8
从右找<501:
- j=6 : 170<501 → 交换5和6
{462, 89, 276, 61, 90, 170, 501, 897, 908, 653, 512}
- j=6 : 170<501 → 交换5和6
第1趟结果:{462, 89, 276, 61, 90, 170} |501| {897, 908, 653, 512}
第2趟排序(左区间,pivot=462)
当前处理区间:[0,5] ➔ {462, 89, 276, 61, 90, 170}
从右找<462:
- j=5 : 170<462 → 交换0和5
{170, 89, 276, 61, 90, 462}
- j=5 : 170<462 → 交换0和5
从左找>462:
- 未找到 → i=j=5
第2趟结果:{170, 89, 276, 61, 90} |462| |501| {897, 908, 653, 512}
第3趟排序(左区间,pivot=170)
当前处理区间:[0,4] ➔ {170, 89, 276, 61, 90}
从右找<170:
- j=3 : 61<170 → 交换0和3
{61, 89, 276, 170, 90}
- j=3 : 61<170 → 交换0和3
从左找>170:
- i=2 : 276>170 → 交换2和3
{61, 89, 170, 276, 90}
- i=2 : 276>170 → 交换2和3
从右找<170:
- j=2 → i=j=2
第3趟结果:{61, 89} |170| {276, 90} |462| |501| {897, 908, 653, 512}
第4趟排序(左子区间,pivot=61)
当前处理区间:[0,1] ➔ {61, 89}
- 从右找<61:
- 未找到 → i=j=0
第4趟结果:|61| {89} |170| {276, 90} |462| |501| {897, 908, 653, 512}
第5趟排序(右子区间,pivot=276)
当前处理区间:[3,4] ➔ {276, 90}
- 从右找<276:
- j=4 : 90<276 → 交换3和4
{90, 276}
- j=4 : 90<276 → 交换3和4
第5趟结果:|61| {89} |170| |90| |276| |462| |501| {897, 908, 653, 512}
第6趟排序(右大区间,pivot=897)
当前处理区间:[7,10] ➔ {897, 908, 653, 512}
从右找<897:
- j=10 : 512<897 → 交换7和10
{512, 908, 653, 897}
- j=10 : 512<897 → 交换7和10
从左找>897:
- i=1 : 908>897 → 交换1和10
{512, 897, 653, 908}
- i=1 : 908>897 → 交换1和10
从右找<897:
- j=2 : 653<897 → 交换1和2
{512, 653, 897, 908}
- j=2 : 653<897 → 交换1和2
最终结果:|61| |89| |90| |170| |276| |462| |501| |512| |653| |897| |908|
尾声
1 | a[i] = povit ; |
其实已经在swap中被我们处理了,因为swap函数是双向交换,不是单向赋值,povit并没有丢失,所以是不需要另外强调的。





