Issues (18)

src/Tree.php (1 issue)

1
<?php
2
3
declare(strict_types=1);
4
5
namespace MartanLV\Koki;
6
7
/**
8
 * Augmented tree
9
 * Class StaticTree.
10
 *
11
 * @author yourname
12
 */
13
class Tree extends Node
14
{
15
    public $root;
16
17
    /**
18
     * undocumented function.
19
     *
20
     * @param $intervals array of Interval
21
     *
22
     * @return void
23
     */
24
    public function __construct(array $intervals = [], bool $preSorted = false)
25
    {
26
        !$preSorted && usort($intervals, function (IntervalInterface $i0, IntervalInterface $i) {
27
            return $i0->getStart() <=> $i->getStart();
28
        });
29
        $this->root = $this->toTree($intervals);
30
    }
31
32
    /**
33
     * An augmented tree can be built from a simple ordered tree,
34
     * for example a binary search tree or self-balancing binary search tree,
35
     * ordered by the 'low' values of the intervals.
36
     */
37
    public function toTree(array $intervals)
38
    {
39
        $max = 0;
40
        $len = count($intervals);
41
        $mid = (int) floor($len / 2);
42
43
        if (!$len) {
44
            return;
45
        }
46
47
        array_walk($intervals, function (IntervalInterface $el) use (&$max) {
48
            if ($max < $el->getEnd()) {
49
                $max = $el->getEnd();
50
            }
51
        });
52
        $l_intervals = array_splice($intervals, 0, $mid);
53
        $r_intervals = array_splice($intervals, -$mid);
54
        $interval = $intervals ? reset($intervals) : array_pop($l_intervals);
55
        $interval = $interval ?? array_pop($r_intervals);
56
57
        $node = new Node(
58
            $interval,
59
            $this->toTree($l_intervals),
60
            $this->toTree($r_intervals),
61
            $max
62
        );
63
64
        $node->root = &$this;
65
66
        return $node;
67
    }
68
69
    /**
70
     * returns intervals that exclusively fall within range given
71
     * to retrieve eather bound inclusevely, just modify parameters.
72
     *
73
     * @return void
74
     */
75
    public function select(int $low, int $high): array
76
    {
77
        return $this->root ? $this->root->select($low, $high) : [];
78
    }
79
80
    public function selectNode(int $low, int $high): array
81
    {
82
        return $this->root ? $this->root->selectNode($low, $high) : [];
83
    }
84
85
    /**
86
     * rebalance messed up tree overall.
87
     */
88
    public function balance()
89
    {
90
        // todo
91
    }
92
93
    /**
94
     * understandable var dump.
95
     */
96
    public function __debugInfo()
97
    {
98
        $arr = $this->all();
99
100
        usort($arr, function (IntervalInterface $i0, IntervalInterface $i) {
101
            return $i0->getStart() <=> $i->getStart();
102
        });
103
104
        return $arr;
105
    }
106
107
    public function yieldInterSelect(int $low, int $high)
108
    {
109
        return $this->root ? $this->root->yieldInterSelect($low, $high) : [];
110
    }
111
112
    public function interSelectNode(int $low, int $high): array
113
    {
114
        return $this->root ? $this->root->interSelectNode($low, $high) : [];
115
    }
116
117
    public function interSelect(int $low, int $high): array
118
    {
119
        return $this->root ? $this->root->interSelect($low, $high) : [];
120
    }
121
122
    public function yieldSelect(int $low, int $high)
123
    {
124
        return $this->root ? $this->root->yieldSelect($low, $high) : [];
125
    }
126
127
    /**
128
     * @return void
129
     */
130
    public function all(): array
131
    {
132
        return $this->root ? $this->root->all() : [];
133
    }
134
135
    /**
136
     * undocumented function.
137
     *
138
     * @return void
139
     */
140
    public function yieldAll()
141
    {
142
        return $this->root ? $this->root->yieldAll() : [];
143
    }
144
145
    public function removeRegion(int $low, int $high)
146
    {
147
        if (!$this->root) {
148
            return [];
149
        }
150
        foreach ($this->interSelectNode($low, $high) as $node) {
151
            $this->remove($node);
152
        }
153
    }
154
155
    public function remove(IntervalInterface $i)
156
    {
157
        if (!$i->left && !$i->right) {
158
            if ($i->root) {
159
                $i->root = null;
160
            }
161
162
            return;
163
        }
164
165
        if ($i->left && $i->right) {
166
            // todo
167
            return;
168
        }
169
        if ($i->left) {
170
            $i->interval = &$i->left->interval;
171
            $i->left = null;
172
        }
173
174
        if ($i->right) {
175
        }
176
177
        if ($this->max > $i->getEnd()) {
178
            if ($this->left) {
179
                $this->left->add($i);
180
            } else {
181
                $this->left = new Node($i);
182
            }
183
        } else {
184
            $this->max = $i->getEnd();
185
            if ($this->right) {
186
                $this->right->add($i);
187
            } else {
188
                $this->right = new Node($i);
189
            }
190
        }
191
192
        return;
193
        if (!$this->root) {
0 ignored issues
show
IfNode is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
194
            return [];
195
        }
196
        $this->root->remove($i);
197
    }
198
199
    public function add(IntervalInterface $i)
200
    {
201
        if (!$this->root) {
202
            $this->root = new Node($i);
203
204
            return;
205
        }
206
        $this->root->add($i);
207
    }
208
}
209