败者树
很多时候看起来很简单,但是最好自己写一写,这样理解才会更加深刻一些。下面是今天练手写的败者树php实现。
// 测试数据 $data_input = array( array(2, 5, 10, 14, 20, 21, 23, 25, 30), array(1, 6, 9, 13, 17), array(3, 8, 12, 16, 19), array(4, 7, 11, 15, 18), ); // 调用代码示例 k_merge($data_input); find_x($data_input, 10); global $b, $k; // $b 为败者树上的叶子结点值, $k为归并的路数量 define('MINVALUE', -65535); // 定义最小值 define('MAXVALUE', 65536); // 定义最大值 /** * k 路归并排序 */ function k_merge($data_input) { global $b, $k; $k = count($data_input); for ($i = 0; $i< $k; $i++) { $b[$i] = array_shift($data_input[$i]); } $loser_tree = array(); create_loser_tree($loser_tree); while ($b[$loser_tree[0]] !== MAXVALUE){ $key = $loser_tree[0]; $value = $b[$key]; print "\n " . $value . " from $key" ; $b[$key] = array_shift($data_input[$key]); $b[$key] = $b[$key] === null ? MAXVALUE : $b[$key]; adjust_loser_tree($loser_tree, $key); } } /** * 从 k 段有序序列中找到 第 x 小的数据 */ function find_x($data_input, $x) { global $b, $k; $k = count($data_input); for ($i = 0; $i< $k; $i++) { $b[$i] = array_shift($data_input[$i]); } $loser_tree = array(); create_loser_tree($loser_tree); for ($x_i = 1; $x_i <= $x - 1; $x_i++) { $key = $loser_tree[0]; $value = $b[$key]; // print "\n -- $key " . $value ; $b[$key] = array_shift($data_input[$key]); $b[$key] = $b[$key] === null ? MAXVALUE : $b[$key]; adjust_loser_tree($loser_tree, $key); } $key = $loser_tree[0]; $value = $b[$key]; print "\n" . $value . "\n"; } /** * 创建败者树 */ function create_loser_tree(&$loser_tree) { global $b, $k; $b[$k] = MINVALUE; //下面初始化调整败者树会用到 for ($i = 0; $i<$k; $i++) { $loser_tree[$i] = $k; } for ($i = $k - 1; $i >=0; $i--) { adjust_loser_tree($loser_tree, $i); // var_dump(" adjusted $i", $loser_tree); } } /** * 重新调整败者树 */ function adjust_loser_tree(&$loser_tree, $s) { global $b, $k; $t = intval(($s + $k) / 2); while ($t > 0) { if ($b[$s] > $b[$loser_tree[$t]]) { $temp = $s; $s = $loser_tree[$t]; $loser_tree[$t] = $temp; } $t = intval($t / 2); } $loser_tree[0] = $s; }