Skip to content

Commit 005e20a

Browse files
committed
🚨 Fix methods complexity
1 parent 55e49b7 commit 005e20a

1 file changed

Lines changed: 165 additions & 74 deletions

File tree

‎src/SortedCollection/TreeNode.php‎

Lines changed: 165 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,23 @@ public function count(): int
260260
* @since 1.0.0
261261
*/
262262
public function find($key, $comparator, $type = 0)
263+
{
264+
list($node, $cmp) = $this->traverseForFind($key, $comparator);
265+
266+
return $this->resolveFindResult($node, $cmp, $type);
267+
}
268+
269+
/**
270+
* Traverse tree for find operation
271+
*
272+
* @param mixed $key The searched key
273+
* @param callable $comparator The comparator function
274+
*
275+
* @return array{0: TreeNode, 1: integer} The closest node and comparison result
276+
*
277+
* @since 1.0.0
278+
*/
279+
private function traverseForFind($key, $comparator)
263280
{
264281
$node = $this;
265282
$cmp = 0;
@@ -276,31 +293,55 @@ public function find($key, $comparator, $type = 0)
276293
}
277294
}
278295

296+
return array($node, $cmp);
297+
}
298+
299+
/**
300+
* Resolve find result from traversal state
301+
*
302+
* @param TreeNode $node The closest node
303+
* @param integer $cmp The key comparison result
304+
* @param integer $type The operation type
305+
*
306+
* @return mixed The resolved node or null
307+
*
308+
* @since 1.0.0
309+
*/
310+
private function resolveFindResult($node, $cmp, $type)
311+
{
279312
if ($cmp < 0) {
280313
if ($type < 0) {
281314
return $node->left;
282-
} elseif ($type > 0) {
315+
}
316+
317+
if ($type > 0) {
283318
return $node;
284-
} else {
285-
return null;
286319
}
287-
} elseif ($cmp > 0) {
320+
321+
return null;
322+
}
323+
324+
if ($cmp > 0) {
288325
if ($type < 0) {
289326
return $node;
290-
} elseif ($type > 0) {
291-
return $node->right;
292-
} else {
293-
return null;
294327
}
295-
} else {
296-
if ($type < -1) {
297-
return $node->predecessor;
298-
} elseif ($type > 1) {
299-
return $node->successor;
300-
} else {
301-
return $node;
328+
329+
if ($type > 0) {
330+
return $node->right;
302331
}
332+
333+
return null;
334+
}
335+
336+
if ($type < -1) {
337+
return $node->predecessor;
303338
}
339+
340+
if ($type > 1) {
341+
return $node->successor;
342+
}
343+
344+
return $node;
304345
}
305346

306347
/**
@@ -560,82 +601,132 @@ public function remove($key, $comparator)
560601
$cmp = call_user_func($comparator, $key, $this->keyInternal);
561602

562603
if ($cmp < 0) {
563-
if ($this->information & 2) {
564-
$left = $this->left;
604+
return $this->removeFromLeft($key, $comparator);
605+
}
565606

566-
if (!$left instanceof self) {
567-
return $this;
568-
}
607+
if ($cmp > 0) {
608+
return $this->removeFromRight($key, $comparator);
609+
}
569610

570-
$leftBalance = $left->information & ~3;
571-
$this->left = $left->remove($key, $comparator);
611+
return $this->removeCurrent();
612+
}
572613

573-
if (
574-
!($this->information & 2)
575-
|| $leftBalance != 0 && ($this->left instanceof self) && ($this->left->information & ~3) == 0
576-
) {
577-
return $this->incBalance();
578-
}
614+
/**
615+
* Remove from left subtree
616+
*
617+
* @param mixed $key The key
618+
* @param callable $comparator The comparator function
619+
*
620+
* @return TreeNode|null The new root
621+
*
622+
* @since 1.0.0
623+
*/
624+
private function removeFromLeft($key, $comparator)
625+
{
626+
if ($this->information & 2) {
627+
$left = $this->left;
628+
629+
if (!$left instanceof self) {
630+
return $this;
579631
}
580-
} elseif ($cmp > 0) {
581-
if ($this->information & 1) {
582-
$right = $this->right;
583632

584-
if (!$right instanceof self) {
585-
return $this;
586-
}
633+
$leftBalance = $left->information & ~3;
634+
$this->left = $left->remove($key, $comparator);
587635

588-
$rightBalance = $right->information & ~3;
589-
$this->right = $right->remove($key, $comparator);
636+
if (
637+
!($this->information & 2)
638+
|| $leftBalance != 0 && ($this->left instanceof self) && ($this->left->information & ~3) == 0
639+
) {
640+
return $this->incBalance();
641+
}
642+
}
590643

591-
if (
592-
!($this->information & 1)
593-
|| $rightBalance != 0 && ($this->right instanceof self) && ($this->right->information & ~3) == 0
594-
) {
595-
return $this->decBalance();
596-
}
644+
return $this;
645+
}
646+
647+
/**
648+
* Remove from right subtree
649+
*
650+
* @param mixed $key The key
651+
* @param callable $comparator The comparator function
652+
*
653+
* @return TreeNode|null The new root
654+
*
655+
* @since 1.0.0
656+
*/
657+
private function removeFromRight($key, $comparator)
658+
{
659+
if ($this->information & 1) {
660+
$right = $this->right;
661+
662+
if (!$right instanceof self) {
663+
return $this;
597664
}
598-
} else {
599-
if ($this->information & 1) {
600-
$right = $this->right;
601665

602-
if (!$right instanceof self) {
603-
return $this;
604-
}
666+
$rightBalance = $right->information & ~3;
667+
$this->right = $right->remove($key, $comparator);
605668

606-
$rightBalance = $right->information & ~3;
607-
$this->right = $right->pullUpLeftMost();
669+
if (
670+
!($this->information & 1)
671+
|| $rightBalance != 0 && ($this->right instanceof self) && ($this->right->information & ~3) == 0
672+
) {
673+
return $this->decBalance();
674+
}
675+
}
608676

609-
if (
610-
!($this->information & 1)
611-
|| $rightBalance != 0 && ($this->right instanceof self) && ($this->right->information & ~3) == 0
612-
) {
613-
return $this->decBalance();
614-
}
615-
} else {
616-
$left = $this->left;
617-
$right = $this->right;
677+
return $this;
678+
}
618679

619-
if ($this->information & 2) {
620-
$left->right = $right;
680+
/**
681+
* Remove current node key
682+
*
683+
* @return TreeNode|null The new root
684+
*
685+
* @since 1.0.0
686+
*/
687+
private function removeCurrent()
688+
{
689+
if ($this->information & 1) {
690+
$right = $this->right;
621691

622-
return $left;
623-
} else {
624-
if ($left && $left->right == $this) {
625-
$left->information &= ~ 1;
692+
if (!$right instanceof self) {
693+
return $this;
694+
}
626695

627-
return $right;
628-
} elseif ($right && $right->left == $this) {
629-
$right->information &= ~ 2;
696+
$rightBalance = $right->information & ~3;
697+
$this->right = $right->pullUpLeftMost();
630698

631-
return $left;
632-
} else {
633-
return null;
634-
}
635-
}
699+
if (
700+
!($this->information & 1)
701+
|| $rightBalance != 0 && ($this->right instanceof self) && ($this->right->information & ~3) == 0
702+
) {
703+
return $this->decBalance();
636704
}
705+
706+
return $this;
637707
}
638708

639-
return $this;
709+
$left = $this->left;
710+
$right = $this->right;
711+
712+
if ($this->information & 2) {
713+
$left->right = $right;
714+
715+
return $left;
716+
}
717+
718+
if ($left && $left->right == $this) {
719+
$left->information &= ~ 1;
720+
721+
return $right;
722+
}
723+
724+
if ($right && $right->left == $this) {
725+
$right->information &= ~ 2;
726+
727+
return $left;
728+
}
729+
730+
return null;
640731
}
641732
}

0 commit comments

Comments
 (0)