1. 特色

  • 不肯定是齐全二叉树

  • 肯定是温和二叉树

  • 叶子结点存储的是理论的值,非叶子结点存的是自定义的内容

2. 工夫复杂度

操作工夫复杂度
查问O(logn)

3. 线段树的图解

4. 代码

<?php/** * content: 线段树(区间树) * create: 2020-11-12 */namespace HeapBundle;use ArrayBundle\BaseArray;class SegmentTreeHeap{    /**     * 传入的数组对象     * @var BaseArray      */    protected $array;    /**     * 数组     * @var array      */    protected $tree = [];    public function __construct(BaseArray $array)    {        $this->array = $array;        $this->build(0, 0, $this->array->getSize() - 1);    }    /**     * 构建线段树     * @param int $treeIndex     * @param int $min     * @param int $max     * @throws \Exception     */    public function build(int $treeIndex, int $min, int $max)    {        // 如果线段区间的最小值和最小值雷同,则示意为叶子结点        if ($min == $max) {            $this->tree[$treeIndex] = $this->array->get($max);            return;        }        // 四舍五入取两头值  最大值减最小值而后除以2拿到两头值,并加上最小值        $mid = floor(($max - $min) / 2) + $min;        // 获取左儿子的索引值,并递归往下构建        $leftIndex = $this->leftChildIndex($treeIndex);        $this->build($leftIndex, $min, $mid);        // 获取右儿子的索引值,并递归往下构建        $rightIndex = $this->rightChildIndex($treeIndex);        $this->build($rightIndex, $mid + 1, $max);        // 非叶子结点的值保留的是它上面所有结点的相加值, 这里能够改为它上面结点的总和值        $this->tree[$treeIndex] = $this->tree[$leftIndex] . '+' . $this->tree[$rightIndex];    }    /**     * 打印线段树     */    public function varDump()    {        ksort($this->tree);        print_r($this->tree);    }    /**     * 获取线段树的长度     * @return int     */    public function getSize(): int    {        return count($this->tree);    }    /**     * 获取左儿子索引     * @param int $parentIndex     * @return int     * @throws \Exception     */    public function leftChildIndex(int $parentIndex): int    {        if ($parentIndex < 0) throw new \Exception('父结点的索引不能小于0');        return $parentIndex * 2 + 1;    }    /**     * 获取右儿子索引     * @param int $parentIndex     * @return int     * @throws \Exception     */    public function rightChildIndex(int $parentIndex): int    {        if ($parentIndex < 0) throw new \Exception('父结点的索引不能小于0');        return $parentIndex * 2 + 2;    }}

5.示例

<?phprequire_once __DIR__ . '/../../vendor/autoload.php';$array = new ArrayBundleBaseArray();for ($i = 0; $i < 10; $i++) { $array->addLast($i + 10);}$heap = new HeapBundleSegmentTreeHeap($array);$heap->varDump();
Array(    [0] => 10+11+12+13+14+15+16+17+18+19    [1] => 10+11+12+13+14    [2] => 15+16+17+18+19    [3] => 10+11+12    [4] => 13+14    [5] => 15+16+17    [6] => 18+19    [7] => 10+11    [8] => 12    [9] => 13    [10] => 14    [11] => 15+16    [12] => 17    [13] => 18    [14] => 19    [15] => 10    [16] => 11    [23] => 15    [24] => 16)