二叉堆 binary heap (2) 利用小根堆求最大 top k
使操作被快速執行的性質是堆序(heap order)性. 由於我們想要快速地找出最小元,因此最小元應該在根上.
類似的,可以宣告一個max堆,找到和刪除最大元
在一個堆中,對於每一個節點X,X的parent中的關鍵字<=X中的關鍵字, 根節點除外(它沒有parent).
* Heap/BinMinHeap.php
<?php /** * 完全二叉樹的陣列實現 * ============================== * A * / \ * B C * / \ / \ * D E F G * /\ / * H I J * =============================== * _ A B C D E F G H I J _ _ _ * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 */ namespace Heap; use util\Comparator; class BinMinHeap { /** @var int */ protected $capacity; /** @var int */ protected $size; /** @var \SplFixedArray */ protected $elements; /** @var Comparator */ protected $comparator; const MIN_PQSIZE = 1; const MIN_DATA = null; public function __construct(int $maxElements, Comparator $cmp) { if ($maxElements < self::MIN_PQSIZE) { throw new \AssertionError("Priority queue size is too small"); } $this->elements = new \SplFixedArray($maxElements + 1); $this->capacity = $maxElements; $this->size = 0; /* dumb position 0 */ $this->elements[0] = self::MIN_DATA; $this->comparator = $cmp; } public function isFull() { return $this->size >= $this->capacity; } public function insert($x) { if ($this->isFull()) { throw new \RuntimeException("Priority queue is full"); } for ($i = ++$this->size; $this->elements[$i>>1] > $x; $i >>= 1) { $this->elements[$i] = $this->elements[ $i>>1 ]; } $this->elements[ $i ] = $x; } public function isEmpty() { return $this->size === 0; } public function deleteMin() { if ($this->isEmpty()) { return $this->elements[0]; } $minElement = $this->elements[1]; $lastElement = $this->elements[$this->size--]; for ($i = 1; $i * 2 <= $this->size; $i = $child) { /* find smaller child */ $child = $i * 2; if ($child !== $this->size && $this->comparator->lessThan( $this->elements[$child+1], $this->elements[$child])) { $child++; } /* Percolate one level */ if ($this->comparator->greeterThan($lastElement, $this->elements[$child])) { $this->elements[$i] = $this->elements[$child]; } else { break; } } $this->elements[$i] = $lastElement; return $minElement; } public function findMin() { return $this->isEmpty() ? $this->elements[0] : $this->elements[1]; } public function __destruct() { for ($i = $this->size-1; $i >= 0; $i--) { unset($this->elements[$i]); } $this->elements = null; } public function makeEmpty() { $this->size = 0; } public function getComparator() { return $this->comparator; } public function __toString() { if (0 === $this->size) { $s = "[]"; } else { $s = '['; for ($i = 1, $last = $this->size+1; $i < $last; $i++) { $s .= json_encode($this->elements[$i]).','; } $s[strlen($s)-1] = ']'; } return sprintf("{capacity: %d, size: %d, elements: %s}", $this->capacity, $this->size, $s); } public function getElements() { $e = []; for ($i = 1, $last = $this->size+1; $i < $last; $i++) { $e[] = $this->elements[$i]; } return $e; } }
* Heap/TopK.php
<?php /** * Created by PhpStorm. * User: Mch * Date: 2018/11/3 * Time: 2:50 PM */ namespace Heap; use util\Comparator; class TopK { /** @var BinMinHeap */ private $heap; public function __construct(array $a, int $k, Comparator $cmp = null) { if ($k < 1 || $k > count($a)) { throw new \LengthException('k < 1 or > count($a)'); } if (is_null($cmp)) { $cmp = new Comparator(); } $heap = new BinMinHeap($k, $cmp); while ( ! $heap->isFull() ) { $heap->insert(current($a)); } while ( ($c = current($a)) !== false ) { if ( ! $heap->getComparator()->lessThan($c, $heap->findMin()) ) { $heap->deleteMin(); $heap->insert($c); } next($a); } $this->heap = $heap; } public function insert($x) { if (! $this->heap->getComparator()->lessThan($x, $this->heap->findMin()) ) { $this->heap->deleteMin(); $this->heap->insert($x); } } public function bulkInsert(array $a) { foreach ($a as $v) { $this->insert($v); } } public function getElements() { return $this->heap->getElements(); } public function __toString() { return $this->heap->__toString(); } }
* util/Comparator.php
<?php namespace util; class Comparator { /** @var callable */ protected $compare; public function __construct(callable $compareFunction = null) { if (is_null($compareFunction)) { $this->compare = function($a, $b) { if ($a === $b) {return 0;} return $a > $b ? 1 : -1; }; return; } $this->compare = $compareFunction; } /*** @return bool */ public function equal($a, $b) { return call_user_func($this->compare, $a, $b) === 0; } /*** @return bool */ public function lessThan($a, $b) { return call_user_func($this->compare, $a, $b) < 0; } /*** @return bool */ public function greeterThan($a, $b) { return call_user_func($this->compare, $a, $b) > 0; } /*** @return bool */ public function lessThanOrEqual($a, $b) { return $this->lessThan($a, $b) || $this->equal($a, $b); } /*** @return bool */ public function greeterThanOrEqual($a, $b) { return $this->greeterThan($a, $b) || $this->equal($a, $b); } public function reverse() { $compareOriginal = $this->compare; $this->compare = function ($a, $b) use ($compareOriginal) { return $compareOriginal($b, $a); }; } }
* autoload.php
<?php
$prefixList = ['Heap', 'util'];
array_walk($prefixList, function($prefix) {
spl_autoload_register(function($class) use ($prefix) {
$base_dir = __DIR__ . DIRECTORY_SEPARATOR. str_replace('\\', '/', $prefix);
// echo $base_dir.PHP_EOL;
$len = strlen($prefix);
if (strncmp($prefix, $class, $len) !== 0) {
return;
}
$relative_class = substr($class, $len);
$file = $base_dir . str_replace('\\', '/', $relative_class) . '.php';
// echo $file.PHP_EOL;
if (!file_exists($file)) {
throw new InvalidArgumentException($file.' does not exist');
}
require $file;
});
}, null);
* index.php
<?php
include './autoload.php';
use Heap\TopK;
use util\Comparator;
// 求出現頻率最高的前2個字母
$a = [
['char'=> 'c', 'freq'=> 12],
['char'=> 'e', 'freq'=> 16],
['char'=> 'b', 'freq'=>9],
['char'=> 'd', 'freq'=> 13],
['char'=> 'a', 'freq'=>5],
['char'=> 'f', 'freq'=> 45]
];
$b = new TopK($a, 2, new Comparator(
function($a, $b) {return $a['freq'] - $b['freq'];}
));
echo json_encode($b->getElements()).PHP_EOL;
$b->bulkInsert([
['char' => 'g', 'freq' => 50],
['char' => 'h', 'freq' => 40],
]);
echo json_encode($b->getElements()).PHP_EOL;
echo $b.PHP_EOL;
unset($a, $b);
// 去掉空格 求ASCII最大的3個字母
$s = "The SplPriorityQueue class";
$s = preg_replace('/\s+/', '', $s);
for ($i = 0, $n = strlen($s); $i < $n; $i++) {
$s[$i] = chr( ord($s[$i]) & 0xdf );
}
echo $s.PHP_EOL; // THESPLPRIORITYQUEUECLASS
$a = str_split($s);
$b = new TopK($a, 3, new Comparator(function($a, $b) {
return strcmp($a, $b);
}));
// ACEEEHIILLOPPQRRSSSTTUUY
echo implode('', $b->getElements()).PHP_EOL; // UYU
* test
$ php index.php
[{"char":"e","freq":16},{"char":"f","freq":45}]
[{"char":"f","freq":45},{"char":"g","freq":50}]
{capacity: 2, size: 2, elements: [{"char":"f","freq":45},{"char":"g","freq":50}]}
THESPLPRIORITYQUEUECLASS
UYU
相關推薦
二叉堆 binary heap (2) 利用小根堆求最大 top k
使操作被快速執行的性質是堆序(heap order)性. 由於我們想要快速地找出最小元,因此最小元應該在根上. 類似的,可以宣告一個max堆,找到和刪除最大元 在一個堆中,對於每一個節點X,X的parent中的關鍵字<=X中的關鍵字, 根節點除外(它沒有p
二叉樹(建立、遍歷、樹的最大深度和最小深度)
樹的引出最初是由二分查詢的原理引出來的,一般順序查詢演算法的複雜度為O(N),而一般二分查詢的複雜度為logN 一個二分查詢演算法可以用一顆查詢樹來表示,樹的根結點為順序陣列的中點,這樣依次查詢效率等同於二分查詢演算法 一般的樹用陣列表示或連結串列表示都會造成空間的浪費,而
【BZOJ3625】【CF438E】小朋友和二叉樹 NTT 生成函式 多項式開根 多項式求逆
題目大意 考慮一個含有n個互異正整數的序列c1,c2,…,cn。如果一棵帶點權的有根二叉樹滿足其所有頂點的權值都在集合{c1,c2,…,cn}中,我們的小朋友就會將其稱作神犇的。並且他認為,一棵帶點權的樹的權值,是其所有頂點權值的總和。 給出一個整數
常用資料結構與演算法:二叉堆(binary heap)
一:什麼是二叉堆 二:二叉堆的實現 三:使用二叉堆的幾個例子 一:什麼是二叉堆 1.1:二叉堆簡介 二叉堆故名思議是一種特殊的堆,二叉堆具有堆的性質(父節點的鍵值總是大於或等於(小於或等於)任何一個子節點的鍵值),二叉堆又具有二叉樹的性質(二叉堆是完全二叉樹
[資料結構與演算法]-二叉堆(binary heap)介紹及其實現(Java)
本文歡迎轉載,轉載前請聯絡作者。若未經允許轉載,轉載時請註明出處,謝謝! http://blog.csdn.net/colton_null 作者:喝酒不騎馬 Colton_Null from CSDN 一.什麼是二叉堆? 二叉堆(binary heap)
資料結構實現 6.2:優先佇列_基於最大二叉堆實現(C++版)
資料結構實現 6.2:優先佇列_基於最大二叉堆實現(C++版) 1. 概念及基本框架 2. 基本操作程式實現 2.1 入隊操作 2.2 出隊操作 2.3 查詢操作 2.4 其他操作 3. 演算法複雜度分析
實驗五:樹和二叉樹的實驗2
使用二叉樹的鏈式儲存結構,建立一棵二叉樹,進行前序、中序以及後序遍歷,同時求得二叉樹的結點個數以及葉子結點個數。 程式原始碼: # ifndef Bitree_H # define Bitree_H struct BiNode { char data; BiNode *lchi
堆排序,分別利用大根堆、小根堆排序
#include <iostream> using namespace std; //下沉調整(本質上都是上浮調整,只不過是將最小元素上浮) void downAdjust(int array[],int parentIndex,int length) { in
1-6 統計二叉樹度為2的結點個數 (10 分)
本題要求實現一個函式,可統計二叉樹中度為2的結點個數。 函式介面定義: int NodeCount ( BiTree T); T是二叉樹樹根指標,函式NodeCount返回二叉樹中度為2的結點個數,若樹為空,返回0。 裁判測試程式樣例: #include <stdio.
Codeforces Round #303 (Div. 2) E 最短路迪傑斯特拉(小根堆實現)
連結:戳這裡 E. Paths and Trees time limit per test3 seconds memory limit per test256 megabytes inputstandard input outputstandard output
給定二叉搜尋樹和兩個整數A,B (最小整數和最大整數)。如何刪除不在該區間內的元素(剪枝)
由於需要檢查樹中的每一個元素,結點的處理順序可以是從葉子結點到根結點。這樣當處理到結點本身時,其左子樹和右字樹為有效剪枝的BST。 static BianrySearchTreeNode PruneB
二叉排序樹(BST) 小講 【 理解 + 例題 】 更新ing ...
很多時候會去忘記,你真正在乎的,是什麼、、、 set 就是用BST來維護集合的一個容器,書上根本沒講、、、、 定義:二叉排序樹(Binary Sort Tree)又稱二叉查詢樹(Binary Search Tree),亦稱二叉搜尋樹。 它或者是一棵空
二叉樹的高度 java 利用遞迴和層次遍歷兩種方法
原文:http://blog.csdn.net/fangchao3652/article/details/53456468 ackage edu.lnu.fang.BiTree; import java.util.ArrayList; import java.util.L
利用棧結構實現二叉樹的非遞迴遍歷,求二叉樹深度、葉子節點數、兩個結點的最近公共祖先及二叉樹結點的最大距離
原文地址:http://blog.csdn.net/forbes_zhong/article/details/51227747 利用棧實現二叉樹的非遞迴遍歷,並求二叉樹的深度、葉子節點數、兩個節點的最近公共祖先以及二叉樹結點的最大距離,部分參考《劍指offer》這本書
[Swift]LeetCode823. 帶因子的二叉樹 | Binary Trees With Factors
spa count () bsp factors 條件 equal reat int Given an array of unique integers, each integer is strictly greater than 1. We make a binary
【堆】小根堆模板
esp printf 最小值 namespace 記得 class queue 二叉 %d 手寫堆 可以視作是一種完全二叉樹結構 #include<iostream> #include<cstring> #include<algor
【模板】小根堆
names ret %d opened code spa ace cnblogs 一個空格 因為根的實現方法(優先隊列)默認為大根堆,即從大到小排列,所以在需要的時候需要手寫小根堆。 題目描述 如題,初始小根堆為空,我們需要支持以下3種操作: 操作1: 1 x 表示將x插入
scala寫算法-用小根堆解決topK
app unit roo ast atm mark 構建 操作 mnt topK問題是指從大量數據中獲取最大(或最小)的k個數,比如從全校學生中尋找成績最高的500名學生等等. 本問題可采用小根堆解決.思路是先把源數據中的前k個數放入堆中,然後構建堆,使其保持堆序(可以簡單
關於dijkstra的小根堆優化
eat algo 最壞情況 str 但是 lan 部分 是我 算法 YY引言 在NOI2018D1T1中出現了一些很震驚的情況,D1T1可以用最短路解決,但是大部分人都在用熟知的SPFA求解最短路。而SPFA的最壞復雜度能夠被卡到$O(VE)$。就是邊的數量乘以點的數量,
關於小根堆的看法
最近在複習小根堆,看了好多部落格,一些思想記錄一下。 早上自己團隊在比賽的時候,第一道題爆零,老師講是用小根堆解決,所以好好複習了一下小根堆; 首先,小根堆其實就是二叉樹。當然,最出名的是一個叫做堆排序的東東,它的時間複雜度為O(nlogn)。足夠的小吧,此外它還有一個別名叫做二叉樹排序。 贈送