堆排序的php写法
2012-12-07 17:36
211 查看
/** * 小根堆 * 解决最大topN的问题 */ class minRootHeap { private $heap; //堆数据 private $heapsize; //堆大小 private $maxPos; //最大位置(堆大小-1) private $maxParentPos; //最后的父节点位置(后边都是叶子节点了) public function __construct(array $arr){ $this->heap = $arr; //初始化堆 $this->heapsize = count($this->heap); $this->maxPos = $this->heapsize - 1; $this->maxParentPos = (int)ceil($this->heapsize/2)-1; $this->create(); } /** * 获取堆数据 */ public function getHeap(){ return $this->heap; } /** * 两个节点交换 */ private static function swap(&$a, &$b){ $tmp = $a; $a = $b; $b = $tmp; } /** * 获取左子节点pos */ private static function left($i){ return $i*2+1; } /** * 获取右子节点pos */ private static function right($i){ return $i*2+2; } /** * 大根堆 * 细节上: * 每当有节点交换,则从此节点开始自上而下遍历该树枝,直到节点符合堆规则为止 */ private function build($pos){ if($pos > $this->maxParentPos){ return true; } $left = self::left($pos); $right = self::right($pos); $min = $pos; if($left<=$this->maxPos && $this->heap[$left]<$this->heap[$min]){ $min = $left; } if($right<=$this->maxPos && $this->heap[$right]<$this->heap[$min]){ $min = $right; } if($min != $pos){ self::swap($this->heap[$pos], $this->heap[$min]); //递归遍历 $this->build($min); } } /** * 大局是由下往上 * 从最后一个父节点开始,一直到堆顶 */ private function create(){ for($i=$this->maxParentPos;$i>=0;$i--){ $this->build($i); } } /** * 遍历数据比较排序 * 若有数据大于堆顶,则替换之,随即进行堆排序 */ public function traverse(array $arr){ $count = count($arr); for($i=0;$i<$count;$i++){ if($arr[$i] > $this->heap[0]){ $this->heap[0] = $arr[$i]; $this->build(0); } } } }
/**
* 构造数据
*/
ini_set('memory_limit','8M');
$file = dirname(__FILE__) . '/data.txt';
$counter = 0;
for($j=0;$j<10000;$j++){
$counter++;
if($counter%100 == 0) echo $counter."\t".memory_get_usage()."\n";
$arr = array();
for($i=0;$i<1000;$i++){
$arr[] = mt_rand(99,1000000);
}
$str = implode("\n",$arr)."\n";
file_put_contents($file, $str, FILE_APPEND);
}
/**
* 数据排序开始
*/
$start = time();
ini_set('memory_limit','2M');
echo memory_get_usage()."\n";
$top = 1000; //设置topN
$bach = 500; //批量每次取数遍历
$counter = 0;
$isCreateHeap = true;
$arr = array();
$file = dirname(__FILE__) . '/data.txt';
$handle = fopen($file, 'r');
if($handle){
while(!feof($handle)){
$buffer = (int)trim(fgets($handle, 100));
if(empty($buffer)) continue;
$arr[] = $buffer;
$counter++;
// 取前$top个数据建堆
if($isCreateHeap && $counter == $top){
$heap = new minRootHeap($arr);
$isCreateHeap = false;
$arr = array();
$counter = 0;
}
// 遍历数据
if(!$isCreateHeap && $counter == $bach){
$heap->traverse($arr);
$arr = array();
$counter = 0;
}
}
fclose($handle);
}
// 最后一组数据遍历
if(count($arr) > 0){
$heap->traverse($arr);
}
// 得出最终结果topN
print_r($heap->getHeap());
echo memory_get_usage()."\n";
$end = time();
echo 'time:'.($end-$start);
相关文章推荐
- PHP高效率写法
- PHP高效率写法(详解原因)
- ios传图片到服务器 -- php写法
- php实现堆排序
- PHP数3退1面向对象的写法(猴子选大王)
- PHP 高效率写法
- php+mysql非暴力查表的注入语句写法总结
- php-堆排序
- PHP高效率写法
- PHP高效率写法(详解原因)
- ThinkPHP 在 Nginx 下 支持PATHINFO 去掉index.php的写法
- PHP获取当前时间、时间戳的各种格式写法汇总
- php 三元运算符使用说明和写法
- PHP高效率写法(详解原因)
- PHP高效率写法
- php脚本#!/usr/bin/env php写法的好处
- PHP 三元运算符省略写法
- PHP高效率写法
- 关于“约瑟夫环”的php的几种写法
- PHP高效率写法(详解原因)