BinaryTreeAbstract::_delete()   B
last analyzed

Complexity

Conditions 5
Paths 5

Size

Total Lines 27
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 27
rs 8.439
c 0
b 0
f 0
cc 5
eloc 20
nc 5
nop 1
1
<?php
2
/**
3
 * DataStructures for PHP
4
 *
5
 * @link      https://github.com/SiroDiaz/DataStructures
6
 * @copyright Copyright (c) 2017 Siro Díaz Palazón
7
 * @license   https://github.com/SiroDiaz/DataStructures/blob/master/README.md (MIT License)
8
 */
9
namespace DataStructures\Trees;
10
11
use DataStructures\Trees\Traits\CountTrait;
12
use DataStructures\Trees\Interfaces\TreeInterface;
13
use DataStructures\Trees\Interfaces\BinaryNodeInterface;
14
15
/**
16
 * BinaryTreeAbstract
17
 * 
18
 * BinaryTreeAbstract class is an abstract class that implements
19
 * common binary trees methods.
20
 *
21
 * @author Siro Diaz Palazon <[email protected]>
22
 */
23
abstract class BinaryTreeAbstract implements TreeInterface {
24
    use CountTrait;
25
    protected $root;
26
    protected $size = 0;
27
28
    abstract public function createNode($key, $data, $parent = null, $left = null, $right = null);
29
    /**
30
     * Checks if the tree is empty.
31
     *
32
     * @return boolean true if is empty, else false.
33
     */
34
    public function empty() : bool {
35
        return $this->root === null;
36
    }
37
38
    /**
39
     * Returns the tree size.
40
     *
41
     * @return int the length
42
     */
43
    public function size() : int {
44
        return $this->size;
45
    }
46
47
    /**
48
     * Inserts data in the correct position.
49
     *
50
     * @param integer|string $key the key used to store.
51
     * @param mixed $data the data to store.
52
     * @param bool $update if false the node isn't updated
53
     *  else if the key matches is updated.
54
     */
55
    public function put($key, $data, $update = false) {
56
        $newNode = $this->createNode($key, $data);
57
        
58
        if($this->root === null) {
59
            $this->root = &$newNode;
60
            $this->size++;
61
            return;
62
        }
63
64
        $parentNode = null;
65
        $current = &$this->root;
66
        while($current !== null) {
67
            $parentNode = &$current;
68
            if($key < $current->key) {
69
                $current = &$current->left;
70
            } else if($key > $current->key) {
71
                $current = &$current->right;
72
            } else {
73
                if($update) {
74
                    $current->data = $data;
75
                    return $newNode;
76
                }
77
                return;
78
            }
79
        }
80
81
        $newNode->parent = &$parentNode;
82
        if($key < $parentNode->key) {
83
            $parentNode->left = &$newNode;
84
        } else {
85
            $parentNode->right = &$newNode;
86
        }
87
        $this->size++;
88
89
        return $newNode;
90
    }
91
    
92
    /**
93
     * Creates a new node or updates it if already exists.
94
     *
95
     * @param int|string $key the key.
96
     * @param mixed $data the data to be stored. 
97
     */
98
    public function putOrUpdate($key, $data) {
99
        $this->put($key, $data, true);
100
    }
101
102
    /**
103
     * Retrieve the data stored in the tree.
104
     *
105
     * @param int|string $key the key to identify the data.
106
     * @return mixed
107
     */
108
    public function get($key) {
109
        if($this->root === null) {
110
            return null;
111
        }
112
113
        $node = $this->root;
114
        while($node !== null) {
115
            if($key < $node->key) {
116
                $node = $node->left;
117
            } else if($key > $node->key) {
118
                $node = $node->right;
119
            } else {
120
                return $node->data;
121
            }
122
        }
123
124
        return null;
125
    }
126
127
    /**
128
     * Returns the root node.
129
     *
130
     * @return DataStructures\Trees\Nodes\BinaryNodeInterface|null the root node.
131
     */
132
    public function getRoot() {
133
        return $this->root;
134
    }
135
136
    /**
137
     * Looks for the node with the given key.
138
     *
139
     * @param int|string $key the key used to look for.
140
     * @return bool true if was found.
141
     */
142
    public function exists($key) : bool {
143
        // $this->_exists($this->root, $key); for recursive search
0 ignored issues
show
Unused Code Comprehensibility introduced by
53% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
144
        if($this->root === null) {
145
            return false;
146
        }
147
148
        if($this->root->key === $key) {
149
            return true;
150
        } else {
151
            $node = $this->root;
152
            while($node !== null) {
153 View Code Duplication
                if($key < $node->key) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
154
                    $node = $node->left;
155
                } else if($key > $node->key) {
156
                    $node = $node->right;
157
                } else {
158
                    return true;
159
                }
160
            }
161
        }
162
163
        return false;
164
    }
165
166
    /**
167
     * Method that retrieves true if found a node with the specified key.
168
     * It's the recursive version of exists method and it's used internally
169
     * for traverse through a root node.
170
     *
171
     * @param DataStructures\Trees\Nodes\BinaryNodeInterface|null $node the root node.
172
     * @param int|string $key the key used to look for.
173
     * @return bool true if exists a node with that key.
174
     */
175
    private function _exists($node, $key) : bool {
176
        if($node === null) {
177
            return false;
178
        }
179
180
        if($node->key === $key) {
181
            return true;
182
        } else if($key < $node->key) {
183
            return $this->_exists($node->left, $key);
184
        } else if($key > $node->key) {
185
            return $this->_exists($node->right, $key);
186
        }
187
    }
188
189
    public function floor($key){}
190
    public function ceil($key){}
191
192
    /**
193
     * Gets the node with the minimum key. The most left and more bottom.
194
     * 
195
     * @return DataStructures\Trees\Nodes\BinaryNodeInterface|null the minum node or
196
     *  null if the tree is empty.
197
     */
198
    public function min() {
199
        if($this->root === null) {
200
            return null;
201
        }
202
203
        if($this->root->left === null) {
204
            return $this->root;
205
        }
206
207
        $current = $this->root;
208
        while($current->left !== null) {
209
            $current = $current->left;
210
        }
211
212
        return $current;
213
    }
214
215
    /**
216
     * Gets the node with the maximum key. The most right and more bottom.
217
     * 
218
     * @return DataStructures\Trees\Nodes\BinaryNodeInterface|null the maximum node or
219
     *  null if the tree is empty.
220
     */
221
    public function max() {
222
        if($this->root === null) {
223
            return null;
224
        }
225
226
        if($this->root->right === null) {
227
            return $this->root;
228
        }
229
230
        $node = $this->root;
231
        while($node->right !== null) {
232
            $node = $node->right;
233
        }
234
235
        return $node;
236
    }
237
238
    /**
239
     * Returns the minimum node from a given node in position X.
240
     *
241
     * @param DataStructures\Trees\Nodes\BinaryNodeInterface $node the start point.
242
     * @return DataStructures\Trees\Nodes\BinaryNodeInterface|null the minimum node.
243
     */
244 View Code Duplication
    protected function getMinNode(BinaryNodeInterface $node = null) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
245
        if($node === null) {
246
            return null;
247
        }
248
249
        while($node->left !== null) {
250
            $node = $node->left;
251
        }
252
253
        return $node;
254
    }
255
256
    /**
257
     * Returns the maximum node from a given node in position X.
258
     *
259
     * @param DataStructures\Trees\Nodes\BinaryNodeInterface $node the start point.
260
     * @return DataStructures\Trees\Nodes\BinaryNodeInterface|null the maximum node.
261
     */
262 View Code Duplication
    protected function getMaxNode(BinaryNodeInterface $node = null) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
263
        if($node === null) {
264
            return null;
265
        }
266
        
267
        while($node->right !== null) {
268
            $node = $node->right;
269
        }
270
271
        return $node;
272
    }
273
    
274
    /**
275
     * Deletes the node with the minimum key and returns it. The most left and more bottom.
276
     * 
277
     * @param DataStructures\Trees\Nodes\BinaryNodeInterface|null if null takes the root.
278
     * @return DataStructures\Trees\Nodes\BinaryNodeInterface|null the minimum node or
279
     *  null if the tree is empty.
280
     */
281 View Code Duplication
    public function deleteMin(BinaryNodeInterface $node = null) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
282
        $node = $this->getMinNode($node ?? $this->root);
283
        if($node !== null) {
284
            $this->_delete($node);
285
        }
286
        
287
        return $node;
288
    }
289
    
290
    /**
291
     * Deletes the node with the maximum key and returns it. The most right and more bottom.
292
     * 
293
     * @param DataStructures\Trees\Nodes\BinaryNodeInterface|null if null takes the root.
294
     * @return DataStructures\Trees\Nodes\BinaryNodeInterface|null the maximum node or
295
     *  null if the tree is empty.
296
     */
297 View Code Duplication
    public function deleteMax(BinaryNodeInterface $node = null) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
298
        $node = $this->getMaxNode($node ?? $this->root);
299
        if($node !== null) {
300
            $this->_delete($node);
301
        }
302
303
        return $node;
304
    }
305
306
    /**
307
     * Deletes the node with the maximum key and returns it. The most right and more bottom.
308
     * 
309
     * @param DataStructures\Trees\Nodes\BinaryNodeInterface|null if null takes the root.
310
     * @return DataStructures\Trees\Nodes\BinaryNodeInterface|null the maximum node or
311
     *  null if the tree is empty.
312
     */
313
    public function delete($key) {
314
        $deleteNode = $this->search($key);
315
        if($deleteNode !== null) {
316
            $this->_delete($deleteNode);
317
            return $deleteNode;
318
        }
319
320
        return null;
321
    }
322
323
    /**
324
     * Deletes the selected node if is not null and returns the node
325
     * that replaces the deleted node. Also decrease the size of tree.
326
     *
327
     * @param DataStructures\Trees\Nodes\BinaryNodeInterface|null The node to be deleted.
328
     * @return the node that replaces the deleted.
329
     */
330
    protected function _delete(BinaryNodeInterface &$node) {
331
        if($node !== null) {
332
            $nodeToReturn = null;
333
            if($node->left === null) {
0 ignored issues
show
Bug introduced by
Accessing left on the interface DataStructures\Trees\Int...ces\BinaryNodeInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
334
                $nodeToReturn = $this->replace($node, $node->right);
0 ignored issues
show
Bug introduced by
Accessing right on the interface DataStructures\Trees\Int...ces\BinaryNodeInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
Documentation introduced by
$node is of type object<DataStructures\Tr...es\BinaryNodeInterface>, but the function expects a object<DataStructures\Tr...es\BinaryNodeInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
335
            } else if($node->right === null) {
0 ignored issues
show
Bug introduced by
Accessing right on the interface DataStructures\Trees\Int...ces\BinaryNodeInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
336
                $nodeToReturn = $this->replace($node, $node->left);
0 ignored issues
show
Bug introduced by
Accessing left on the interface DataStructures\Trees\Int...ces\BinaryNodeInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
Documentation introduced by
$node is of type object<DataStructures\Tr...es\BinaryNodeInterface>, but the function expects a object<DataStructures\Tr...es\BinaryNodeInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
337
            } else {
338
                $successorNode = $this->getMinNode($node->right);
0 ignored issues
show
Bug introduced by
Accessing right on the interface DataStructures\Trees\Int...ces\BinaryNodeInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
339
                if($successorNode->parent !== $node) {
340
                    $this->replace($successorNode, $successorNode->right);
341
                    $successorNode->right = &$node->right;
0 ignored issues
show
Bug introduced by
Accessing right on the interface DataStructures\Trees\Int...ces\BinaryNodeInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
342
                    $successorNode->right->parent = &$successorNode;
343
                }
344
345
                $this->replace($node, $successorNode);
346
                $successorNode->left = &$node->left;
347
                $successorNode->left->parent = &$successorNode;
348
                $nodeToReturn = &$successorNode;
349
            }
350
351
            $this->size--;
352
            return $nodeToReturn;
353
        }
354
355
        return null;
356
    }
357
358
    /**
359
     * Replaces the node n to remove a new one k and links k with the parent
360
     * of n.
361
     *
362
     * @param DataStructures\Trees\Nodes\BinaryNodeInterface $nodeToReplace the node to remove.
363
     * @param DataStructures\Trees\Nodes\BinaryNodeInterface|null $newNode the newNode
364
     *  to link with the $nodeToReplace parent.
365
     * @return DataStructures\Trees\Nodes\BinaryNodeInterface the new linked node.
366
     */
367
    protected function replace(&$nodeToReplace, &$newNode) {
368
        if($nodeToReplace->parent === null) {
369
            $this->root = &$newNode;
370
        } else if($nodeToReplace === $nodeToReplace->parent->left) {
371
            $nodeToReplace->parent->left = &$newNode;
372
        } else if($nodeToReplace === $nodeToReplace->parent->right) {
373
            $nodeToReplace->parent->right = &$newNode;
374
        }
375
376
        if($newNode !== null) {
377
            $newNode->parent = &$nodeToReplace->parent;
378
        }
379
380
        return $newNode;
381
    }
382
383
    /**
384
     * Retrieves the node with the specified key.
385
     *
386
     * @param int|string $key the key used to store.
387
     * @return DataStructures\Trees\Nodes\BinaryNodeInterface|null the node or null.
388
     */
389
    public function search($key) {
390
        if($this->root === null) {
391
            return null;
392
        }
393
394
        if($this->root->key === $key) {
395
            return $this->root;
396
        } else {
397
            $node = $this->root;
398
            while($node !== null) {
399 View Code Duplication
                if($key < $node->key) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
400
                    $node = $node->left;
401
                } else if($key > $node->key) {
402
                    $node = $node->right;
403
                } else {
404
                    return $node;
405
                }
406
            }
407
        }
408
409
        return null;
410
    }
411
    
412
    /**
413
     * Returns true if is leaf the node.
414
     *
415
     * @param DataStructures\Trees\Nodes\BinaryNodeInterface|null $node default to null.
416
     * @return true if is leaf the node, is not null and their subtrees has no
417
     *  pointers to successors.
418
     */
419
    public function isLeaf($node) : bool { // BinaryTreeNode
420
        return ($node !== null && $node->left === null && $node->right === null);
421
    }
422
423
    /**
424
     * Checks if a node is root. New nodes that does not point to any other node
425
     * also are called a root node.
426
     *
427
     * @param DataStructures\Trees\Nodes\BinaryNodeInterface|null $node default to null.
428
     * @return true if is root the node, is not null and their subtrees has no
429
     *  pointers to successors.
430
     */
431
    public function isRoot($node) : bool {
432
        return $node !== null && $node->parent === null;
433
    }
434
435
    /**
436
     * Traverse in preorder. This is: first visit the root, then
437
     * the left subtree and finally the right subtree.
438
     *
439
     * @param Callable|null $callback the callback function to apply to each
440
     *  node.
441
     */
442
    public function preorder(Callable $callback = null) {
443
        $this->_preorder($this->root, $callback);
444
    }
445
446
    /**
447
     * Private preorder traverse method that is recursive and is called by
448
     * the public preorder method.
449
     *
450
     * @param DataStructures\Trees\Nodes\BinaryNodeInterface|null $node.
0 ignored issues
show
Bug introduced by
There is no parameter named $node.. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
451
     * @param Callable|null $callback the callback function to apply to each
452
     *  node.
453
     */
454 View Code Duplication
    private function _preorder($node, Callable $callback = null) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
455
        if($node === null) {
456
            return;
457
        }
458
        if($callback !== null) {
459
            call_user_func($callback, $node);
460
        }
461
        $this->_preorder($node->left, $callback);
462
        $this->_preorder($node->right, $callback);
463
    }
464
465
    /**
466
     * Traverse in inorder. This is: first visit the left subtree,
467
     * then the root and finally the right subtree.
468
     *
469
     * @param Callable|null $callback the callback function to apply to each
470
     *  node.
471
     */
472
    public function inorder(Callable $callback = null) {
0 ignored issues
show
Unused Code introduced by
The parameter $callback is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
473
        $this->_inorder($this->root);
474
    }
475
476
    /**
477
     * Private inorder traverse method that is recursive and is called by
478
     * the public inorder method.
479
     *
480
     * @param DataStructures\Trees\Nodes\BinaryNodeInterface|null $node.
0 ignored issues
show
Bug introduced by
There is no parameter named $node.. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
481
     * @param Callable|null $callback the callback function to apply to each
482
     *  node.
483
     */
484 View Code Duplication
    private function _inorder($node, Callable $callback = null) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
485
        if($node === null) {
486
            return;
487
        }
488
489
        $this->_inorder($node->left, $callback);
490
        if($callback !== null) {
491
            call_user_func($callback, $node);
492
        }
493
        $this->_inorder($node->right, $callback);
494
    }
495
496
    /**
497
     * Traverse in postorder. This is: first visit the left subtree,
498
     * then the right subtree and finally the root.
499
     *
500
     * @param Callable|null $callback the callback function to apply to each
501
     *  node.
502
     */
503
    public function postorder(Callable $callback = null) {
504
        $this->_postorder($this->root, $callback);
505
    }
506
507
    /**
508
     * Private postorder traverse method that is recursive and is called by
509
     * the public postorder method.
510
     *
511
     * @param DataStructures\Trees\Nodes\BinaryNodeInterface|null $node.
0 ignored issues
show
Bug introduced by
There is no parameter named $node.. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
512
     * @param Callable|null $callback the callback function to apply to each
513
     *  node.
514
     */
515 View Code Duplication
    private function _postorder($node, Callable $callback = null) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
516
        if($node === null) {
517
            return;
518
        }
519
        $this->_postorder($node->left, $callback);
520
        $this->_postorder($node->right, $callback);
521
        if($callback !== null) {
522
            call_user_func($callback, $node);
523
        }
524
    }
525
}