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) : []; |
||
0 ignored issues
–
show
Bug
Best Practice
introduced
by
![]() |
|||
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() : []; |
||
0 ignored issues
–
show
|
|||
133 | } |
||
134 | |||
135 | /** |
||
136 | * undocumented function. |
||
137 | * |
||
138 | * @return void |
||
139 | */ |
||
140 | public function yieldAll() |
||
141 | { |
||
142 | return $this->root ? $this->root->yieldAll() : []; |
||
0 ignored issues
–
show
Are you sure the usage of
$this->root->yieldAll() targeting MartanLV\Koki\Node::yieldAll() seems to always return null.
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||
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) { |
||
0 ignored issues
–
show
|
|||
158 | if ($i->root) { |
||
0 ignored issues
–
show
|
|||
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; |
||
0 ignored issues
–
show
|
|||
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 function fx() {
try {
doSomething();
return true;
}
catch (\Exception $e) {
return false;
}
return false;
}
In the above example, the last ![]() |
|||
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 |