您的位置:首页 > 编程语言 > PHP开发

堆排序的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);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: