<?php
function printList($arElem, $msg){
   echo $msg.PHP_EOL;
   foreach($arElem as $k => $v){
       echo $k.'=>'.$v.' ';
   }
   echo PHP_EOL;
}

function exchange(&$arElem, $m, $n){
   $tmp = $arElem[$m];
   $arElem[$m] = $arElem[$n];
   $arElem[$n] = $tmp;
}

function partion(&$arElem, $p, $r){
   $x = $arElem[$r];
   $i = $p;
   for($j = $p; $j < $r; $j++){
       printList($arElem, '正在排序数组 p:'.$p.';r:'.$r);
       if($arElem[$j] < $x){
           printList($arElem, '找到一个可交换元素 arElem[j]:'.$arElem[$j].'<'.'x:'.$x);
           //比基准数小,放到基准数左边
           if($i != $j){
               exchange($arElem, $i, $j);
           }
           //左侧指针右移一个数,直到该数大于等于基准数
           $i++;
       }
       printList($arElem, '已排序数组 p:'.$p.';r:'.$r);
   }
   //将基准数放到分界点
   printList($arElem, '正在将基准数放到分界点 i:'.$i.';r:'.$r);
   exchange($arElem, $i, $r);
   printList($arElem, '已将基准数放到分界点 i:'.$i.';r:'.$r);
   return $i;
}

function quickSort(&$arElem, $p, $r){
   if($p < $r){
       //找到基准数的位置,让左侧数小于基准数,右侧数大于等于基准数
       printList($arElem, '正在partion p:'.$p.';r:'.$r);
       $mid = partion($arElem, $p, $r);
       printList($arElem, '完成partion p:'.$p.';r:'.$r.';mid:'.$mid);
       //继续排列基准数左侧数组
       printList($arElem, '正在左侧quickSort p:'.$p.';r:'.($mid - 1).';mid:'.$mid);
       quickSort($arElem, $p, $mid - 1);
       printList($arElem, '完成左侧quickSort p:'.$p.';r:'.($mid - 1).';mid:'.$mid);
       //继续排列基准数右侧数组
       printList($arElem, '正在右侧quickSort p:'.($mid + 1).';r:'.$r.';mid:'.$mid);
       quickSort($arElem, $mid + 1, $r);
       printList($arElem, '完成右侧quickSort p:'.($mid + 1).';r:'.$r.';mid:'.$mid);
   }
}

$arElem = [2, 1, 4, 7, 3];
$p = 0;
$r = count($arElem) - 1;
quickSort($arElem, $p, $r);