1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| function min_heap($tree) { $maxIndex = count($tree) - 1; $lastParentIndex = ceil($maxIndex / 2 - 1); $focusIndex = $lastParentIndex; // 关注点从最后一个父节点向上 while ($focusIndex >= 0) { // 关注点逐渐向下比较 $parentIndex = $focusIndex; while ($parentIndex <= $lastParentIndex) { // 不加哨兵,则左子树为2n+1,右子树为2n+2 // 第一个元素未哨兵时候,左子树为2n,右子树为2n+1 $leftIndex = $parentIndex * 2 + 1; $rightIndex = $parentIndex * 2 + 2; // 根据完全二叉树性质,如果右子树超出不存在,则这个父节点中比较小的肯定是左子树 if ($rightIndex > $maxIndex) { $smallIndex = $leftIndex; } else { $smallIndex = $tree[$leftIndex] < $tree[$rightIndex] ? $leftIndex : $rightIndex; } // 利用下沉节点的方式把当前子树,调整为堆 // 选出左右子树中较小的 // 如果子树比父节点还小则下沉父节点 if ($tree[$smallIndex] < $tree[$parentIndex]) { $tmp = $tree[$parentIndex]; $tree[$parentIndex] = $tree[$smallIndex]; $tree[$smallIndex] = $tmp; // 原来的子节点变为新的父节点继续向下比较 $parentIndex = $smallIndex; } else { // 子节点都不小于父节点则开始下一个关注点的操作 break; } } $focusIndex -= 1; }
return $tree; }
$tree = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]; $heap = min_heap($tree);
var_dump($heap);
|