PHP基数排序(MSD模式)

用 PHP 实现算法然后去排序是愚蠢的事情 .

・PHP 的数组并不是真正意义上的数组 , 而是一组有序图 .

・应该尽可能使用可以正确存储数据的最小数据类型 , 更小的数据类型通常更快 , 因为它们占用更少的内存和 CPU 缓存 , 并且处理时需要的 CPU 周期也更少 . 但 PHP 不支持 INT ( int 型占用 4 字节空间 ) , 它的整数类型到底占用多少空间我尚不清楚 , 但是 WinCacheGrind 显示 10 万个随机数组排序 ( 基数快排 ) 使用的空间让我觉得惊讶 .

wKiom1Oi_G-zNOURAAOhYyvYjho175.jpg

居然使用了 14M 的内存 . 10W 个 int 型即使平铺也仅仅需要 390K 而已 , 因此 PHP 的整形到底占用多少字节 ?



呱呱 , 以上先废话两句 . 虽然 PHP 实现起来很坑 , 但这觉不代表斟酌算法就是件无意义的事 , 每个算法都是一种思想的结晶 , 学习优秀的思想 , 开拓思维 . 上代码 . ( 我就不废话原理了 , 到处都有 , 且 LSD 模式代码非常简单 , 因此先上 MSD , 请大虾指正 )


// 取得 $num 的 $pos 位 
function GetNumInPos($num, $pos){
  $temp = 1;
  for ($i = 0; $i < $pos - 1; $i++)
    $temp *= 10;

  return ($num / $temp) % 10;
}

// MSD ( 最高位优先 ) 模式
function MsdRadixSort(& $a, $s, $e, $d) {
 
  $bucket = $count = array();
  
  // 以下三行为求出当前位数相同数字的边界 , 据此分组
  for($i=0; $i<=10; $i++) $count[$i] = 0;
  for($i=$s; $i<=$e; $i++) $count[GetNumInPos($a[$i], $d)]++;
  for($i=1; $i<=10; $i++) $count[$i] += $count[$i-1];
  
  // 将所有数据放入桶
  for($i=$e; $i>=$s; $i--) {
    $j = GetNumInPos($a[$i], $d);
    $bucket[$count[$j]-1] = $a[$i];
    $count[$j]--;
  }
  
  // 将桶内数据放入 $a
  for($i=$s, $j=0; $i<=$e; $i++, $j++) $a[$i] = $bucket[$j];
  $bucket = null; // 谨慎起见 , 释放内存
  
  // 循环处理 $d-1 位
  for($i=1; $i<=10; $i++) {
    $p1 = $s+$count[$i-1];
    $p2 = $s+$count[$i]-1;
    if($p2>$p1 && $d>1) MsdRadixSort($a, $p1, $p2, $d-1);
  }

}


用法 :

MsdRadixSort($a, 0, count($a)-1, $int);// $int 为最大位数 , 比如待排序的数组最大只有 3 位数 , 那么 $int 就写 3 . 5 位就写 5


如果有更好的算法 , 或者发现错误 , 指正哈 .

你可能感兴趣的:(数据结构,算法,基数排序)